Django REST用户创建/身份验证

时间:2020-05-09 23:41:15

标签: python django django-rest-framework

该问题基于一个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')),
]

serializers.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发送,并且返回了相同的结果。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:2)

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

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

答案 1 :(得分:1)

也许您发布的网址错误,请尝试在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/)中有关于此的教程

答案 2 :(得分:1)

基于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