【问题标题】:Django Rest Frame Work: passing User in djago rest frame workDjango Rest Framework:在 Django Rest 框架中传递用户
【发布时间】:2022-01-10 05:40:26
【问题描述】:

我有一个 Django 项目,模型中的代码如下

class Report(models.Model):
    created_by_user=models.ForeignKey(User,on_delete=models.CASCADE)

序列化器中的以下代码

class ReportSerializer(serializers.ModelSerializer):
    class Meta:
        model=Report
        fields='__all__'

以及以下代码

class ReportCreateView(APIView):
    def post(self,request, *args, **kwargs):
        received_data=ReportSerializer(data=request.data)
        if received_data.is_valid():
            received_data.save()
            return Response(received_data.data, status=status.HTTP_201_CREATED)
        return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)

当我通过邮递员发送帖子请求并在“授权”选项卡中发送用户名和密码时 它错误:

{
    "created_by_user": [
        "This field is required."
    ]
}

但如果我输入的用户名或密码不正确,它会是

{
    "detail": "Invalid username/password."
}

大家可以帮帮我吗?

【问题讨论】:

    标签: python django django-models serialization django-rest-framework


    【解决方案1】:

    您的序列化程序不知道当前登录的用户。您将其作为上下文从request. user 或请求传递。

    我个人更喜欢在序列化程序中使用CurrentUserDefault。为了使它工作,我们需要将请求作为上下文传递,因为CurrentUserDefault 从上下文请求中选择用户。我们需要更新我们的视图和序列化代码如下

    视图文件:将请求添加为上下文上下文

    class ReportCreateView(APIView):
    
    
    def post(self,request, *args, **kwargs):
        received_data=ReportSerializer(data=request.data, context = {"request": request})
        if received_data.is_valid():
            received_data.save()
            return Response(received_data.data, status=status.HTTP_201_CREATED)
        return Response(received_data.errors,status.HTTP_400_BAD_REQUEST)
    

    serializer.py:更新您的序列化程序以自动填充 created_by_user

    class ReportSerializer(serializers.ModelSerializer):
        created_by_user = serializers.HiddenField(default=serializers.CurrentUserDefault())
        
        class Meta:
            model=Report
            fields='__all__'
    

    它将解决您的用户字段所需的问题。

    "created_by_user": ["This field is required."]
    

    现在讨论与密码错误有关的问题的下一部分。

    默认情况下,APIView 从设置中选择默认身份验证类别。在项目settings.py 中,我们主要在使用 DRF 时编写这些行,它们用作 APIView 的默认身份验证:

    来自 settings.py

    REST_FRAMEWORK = {
        # Use Django's standard `django.contrib.auth` permissions,
        # or allow read-only access for unauthenticated users.
        "DEFAULT_PERMISSION_CLASSES": [
            "rest_framework.permissions.IsAuthenticated",
        ],
        # Authentication settings
        "DEFAULT_AUTHENTICATION_CLASSES": [
            "rest_framework.authentication.SessionAuthentication",
        ],
       ...
    }
    
    

    在 APIView 中,您可以查看默认的 permission_classesauthentication_classes

    从 APIView 内部:

        authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
        throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
        permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    

    那是您输入无效密码时:

    "detail": "Invalid username/password."
    

    从邮递员那里为您的 APIView 提供正确的用户名和密码,以便它获取请求的登录用户,以便在数据库级别自动填充。

    【讨论】:

    • 这是什么? serializers.HiddenField
    • serializers.HiddenField 用于当您不公开它以供读写时使用。所以它可以用在我们必须填写默认值的地方,仅供内部使用,而不是将其暴露给 API 级别。
    【解决方案2】:

    您不对您的用户数据执行任何处理,只需要保存请求用户,因为我认为您不需要序列化器字段,最好让您当前的用户在视图中。此外,如果您需要更多字段进行序列化,您可以将 created_by_user 设置为 read_only 并在您的视图中设置其值。

    例如,如果您的模型中有报告名称和报告描述字段:

    class Report(models.Model):
        created_by_user = models.ForeignKey(User, on_delete=models.CASCADE)
        name = models.CharField(max_length=256)
        desc = models.TextField()
    

    像这样执行您的序列化程序:

    class ReportSerializer(serializers.ModelSerializer):
        class Meta:
            model = Report
            fields = '__all__'
            extra_kwargs = {
                'created_by_user': {'read_only': True},
            }
    

    然后在您的视图中设置 created_by_user 值:

    class ReportCreateView(APIView):
        def post(self, request, *args, **kwargs):
            request.data['created_by_user'] = request.user # just need add this line 
            received_data = ReportSerializer(data=request.data)
            if received_data.is_valid():
                received_data.save()
                return Response(received_data.data, status=status.HTTP_201_CREATED)
            return Response(received_data.errors, status.HTTP_400_BAD_REQUEST)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-10
      • 1970-01-01
      • 2016-04-08
      • 2014-05-26
      • 2019-03-05
      • 2014-05-08
      • 2019-09-04
      • 1970-01-01
      相关资源
      最近更新 更多