0

我在我的第一个 django、rest-framework 应用程序中遇到了很多问题。

  1. 我注册后没有得到令牌,而不是
“用户”:{
   "_id":"1",
   "用户名":"你",
   “电子邮件”:“a@a.com”
 },
 “令牌”:'fjdjfkljgkghgjkl'
}

我越来越

{
 "_id":"1",
 "username":"you", 
 "email":"a@a.com"
}

这里可能是什么问题?

  1. 当我尝试登录时,邮递员告诉我:
{"username" :["user with this username already exist.]}

我试图登录不注册。为什么会这样?

  1. 当我尝试获取属于该用户的所有待办事项时,我收到此错误:
{"details":"Authentication credantials were not provided" }

,而不是一个空列表,这是为什么呢?

  1. 如果我只有令牌,如何获取用户?

序列化代码:

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('_id', 'username', 'email', 'password')
        extra_kwarg = { 'password' : {
            'write_only' : True
        }}


class SignUpSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('_id', 'username', 'email', 'password')

        extra_kwarg = { 'password' : {
            'write_only' : True
        }}

    def create_user(self, validated_data):
        user = User.objects.create_user(validated_data['username'], validated_data['email'], validated_data['password'])

        return user

class SignInSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('username', 'password')

    def validate(self, data):
        username = data.get("username", None)
        password = data.get("password", None)
        user = authenticate(username=username, password=password)

        if user is None:
           raise serializers.ValidationError('A user with this username and password is not found.')

        return user

视图集代码:

class SignUpViewSet(viewsets.ModelViewSet):
    serializer_class = SignUpSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data = request.data)
        serializer.is_valid(raise_exception = True)
        user = serializer.save()

        return Response({
            'user': SignUpSerializer(user, context = self.get_serializer_context()).data,
            'token': AuthToken.objects.create(user)
        })

class SignInViewSet(viewsets.ModelViewSet):
    serializer_class = SignInSerializer

    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data = request.data)
        serializer.is_valid(raise_exception = True)
        user = serializer.validated_data

        return Response({
            'user': UserSerializer(user, context = self.get_serializer_context()).data,
            'token': AuthToken.objects.create(user)
        })

class GetUserViewSet(viewsets.ModelViewSet):
    permission_classes = [
        permissions.IsAuthenticated
    ] 
    serializer_class = UserSerializer

    def get_object(self):
        return self.request.user

4

1 回答 1

1

您列出的问题主要是造成点的原因2

{"username" :["user with this username already exist.]}

如果您仔细阅读它,它会说用户已经存在。所以它必须尝试创建一个user而不是让他们登录。这种行为是例外的,因为您在SignInViewSet.

class SignInViewSet(viewsets.ModelViewSet):
    serializer_class = SignInSerializer

    def post(self, request, *args, **kwargs):
        serializer = SignInSerializer()
        user = serializer.validate(attrs=request.data)

        return Response({
            'user': UserSerializer(user, context = self.get_serializer_context()).data,
            'token': AuthToken.objects.create(user)
        })

我已删除get_serializer,因为我不熟悉它,但它应该可以正常工作。主要的收获是serializer.is_valid()仅当您在数据库中updatingcreating在数据库中时使用。正如您现在所看到的,它正在尝试创建一个新的用户实例,这就是错误的原因user with this username already exists。在此之后你应该有你的token然后设置Headers你的Postman,如果一切顺利,你可以request.user在你的视图中访问你的用户。

更新:

views.py

from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from knox.models import AuthToken
from .serializers import SignInSerializer, SignUpSerializer, UserSerializer
# Create your views here.

class SignUpView(APIView):
    serializer_class = SignUpSerializer

    def post(self, request):
        serializer = SignUpSerializer(data = request.data)
        if serializer.is_valid():
            user = serializer.save()
            _, token = AuthToken.objects.create(user)
            return Response({'user': serializer.data, 'token': token})
        else:
            return Response(serializer.errors)

serializers.py

class SignUpSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email', 'password')
        extra_kwarg = { 'password' : {'write_only' : True }}

    def create_user(self, validated_data):
        user = User.objects.create_user(username=validated_data['username'], email=validated_data['email'], password=validated_data['password'])
        user.save()
        return user

由于您没有使用viewsets我已经转移SignUpViewviews.py并且我已经删除了您的额外验证,serializers因为它不起作用,相反,如果您的序列化程序中有任何错误,它将在您的视图、检查if serializer.is_valid()else语句中处理。而你urls.pyuser应用内将是这样的。

from rest_framework import routers
from .views import SignUpView
from django.urls import path

# user_router = routers.DefaultRouter()

# user_router.register(r'sign_up', SignUpViewSet, basename='sign_up')
# user_router.register(r'sign_in', SignInViewSet, basename='sign_in')
# user_router.register(r'user', GetUserViewSet, basename='user')

urlpatterns = [
    path('sign_up/', SignUpView.as_view()),
]

并且backend/urls.py将是

from django.contrib import admin
from django.urls import include,path
from todo.urls import todo_router
from django.views.generic import TemplateView

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/todo/', include(todo_router.urls)),
    path('api/auth/', include('user.urls')),
    path('', TemplateView.as_view(template_name = 'index.html'))
]

检查输出:这里

注意: self.get_serializer(data = request.data)仅适用于ViewSets,这就是views.py已编辑的原因。您也可以类似地更新您的其他视图。

于 2020-06-25T11:35:16.883 回答