Django REST 用户创建/身份验证

Posted

技术标签:

【中文标题】Django REST 用户创建/身份验证【英文标题】:Django REST User Creation/Authentication 【发布时间】:2020-08-25 13:15:46 【问题描述】:

本题基于here。我正在为我的 Web 应用程序设置 Django REST 框架,并尝试设置用户帐户。根据 REST 文档,他们将所有帐户代码放在主项目目录中的示例中,并在一个单独的应用程序中也这样做了。这是我所拥有的:

urls.py

from django.contrib import admin
from django.urls import include, path
from django.conf.urls import url
from rest_framework import routers
from . import views

router = routers.DefaultRouter()
router.register('users', views.UserViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    url('', include(router.urls)),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

序列化器.py

from django.contrib.auth.models import User
from rest_framework import serializers


class UserSerializer(serializers.ModelSerializer):
    password = serializers.CharField(write_only=True)

    def create(self, validated_data):
        user = User.objects.create(
            username=validated_data['username']
        )
        user.set_password(validated_data['password'])
        user.save()

        return user

    class Meta:
        model = User
        # Tuple of serialized model fields (see link [2])
        fields = ( "id", "username", "password", )

views.py

from rest_framework import viewsets, permissions
from rest_framework.generics import CreateAPIView
from django.contrib.auth.models import User
from .serializers import UserSerializer


# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class CreateUserView(CreateAPIView):
    model = User
    permission_classes = [
        permissions.AllowAny
    ]
    serializer_class = UserSerializer

我曾尝试在 Chrome 中使用 Boomerang REST 客户端向此 API 发布数据,但它总是返回 403 错误,提示“用户名/密码无效”。具体来说,我使用查询字符串和 2 个参数发送到 http://127.0.0.1:8000/users/create/:用户名和密码。我也尝试将它作为 JSON 发送,它返回相同。任何帮助将不胜感激。

【问题讨论】:

能否为该请求添加django进程的控制台调试 听起来您是在说您正在向/users/create/?username=user&password=password 发帖。对吗? 【参考方案1】:

您的urls.py 中似乎没有注册CreateUserView。您应该能够注册并正常访问它。我认为这应该适合你:

urlpatterns = [
    ...
    url(r'^users/create/', views.CreateUserView.as_view()),
]

也就是说,我建议为您的UserViewSet 添加一个extra action:

# Create your views here.
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated

    @action(methods=['post'], detail=False, permission_classes=[permissions.AllowAny])
    def register(self, request, *args, **kwargs):
        # This logic was taken from the `create` on `ModelViewSet`. Alter as needed.
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

那么您应该可以通过/users/register/ 发帖。你也可以在装饰器上specify your own url name and path。

【讨论】:

这对我有点用。将 CreateUserView 添加到 urls.py 不起作用,但是将操作添加到 UserViewSet 确实可以使用它。但是,我似乎仍然无法从 Boomerang 发布数据,我只能通过基本的 html 表单手动添加。【参考方案2】:

也许你发错了网址,试试在http://127.0.0.1:8000/users/上发布相同的内容, 因为ModelViewSet 会自动添加POST, PATCH, PUT, DELETE and GET 方法。

另外,因为您要求进行身份验证 (permission_classes = [permissions.IsAuthenticated]),您应该在请求中发送此标头。在 DRF 网站 (https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/) 中有一个关于此的教程

【讨论】:

似乎没有帮助。 POST 到 /users/ 仍然会导致错误的用户名/密码响应 @arc-menace 这个Boomerang REST Client 允许标头进行身份验证? 是的。 (显然我的评论必须有足够的字符) 我实际上并没有要求身份验证,因为我需要匿名用户才能访问它。在 CreateUserView 我将权限设置为 AllowAny 以适应此 @arc-menace 在你的UserViewSet 中评论这一行permission_classes = [permissions.IsAuthenticated] 并重复你的POST,如果它有效,你需要为你的其他 ViewSet 找出一个 URL 来创建用户.我的意见是对所有内容都使用相同的 url,正如 Ehsan 所说,在同一个类中实现一个方法,比如 def create(self, request):【参考方案3】:

基于 django-rest-framework documents 最好使用 viewset 来创建用户 api。因此,您需要向http://127.0.0.1:8000/api-auth/users 发送POST 请求,而无需CreateUserView 函数。

但是,如果您想要自定义用户创建 api,您是否需要以下内容:

class UserViewSet(viewsets.ModelViewSet):
    """
    A viewset that provides the standard actions
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

    @action(detail=True, methods=['post'], permission_classes=[permissions.AllowAny])
    def create_user(self, request, pk=None):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

要在 ViewSet 中包含自定义序列化程序,您可以在 ViewSet 的 get_serializer_class 函数中指定它们,如下所示:

class UserViewSet(viewsets.ModelViewSet):
# example viewset
    def get_serializer_class(self):
        if self.action == 'list':
            return ListUserSerializer
        elif self.action == 'create':
            return CreateUserSerializer
        elif self.action == 'update':
            return UpdateUserSerializer
        return DetailUserSerializer

【讨论】:

如果我创建了一个视图集,我的序列化器是好的还是没有必要的? 你可以指定任何你想要的序列化器。只需将其放入您的 ViewSet 中即可。比如:serializer_class= UserSerializer

以上是关于Django REST 用户创建/身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Django REST Framework - API 身份验证 - 授权应用程序而不是用户

Django rest 框架 JWT 和自定义身份验证后端

使用 Django-rest-auth 创建新用户时创建自定义用户模型

Django Rest Framework 不接受 JWT 身份验证令牌

Django REST框架--认证和权限

使用 django-rest-auth 和 allauth 进行 Google 身份验证