【问题标题】:Django REST Framework : "This field is required." with required=False and unique_togetherDjango REST 框架:“此字段是必需的。”与 required=False 和 unique_together
【发布时间】:2016-04-12 05:44:18
【问题描述】:

我想用 Django REST Framework 保存一个简单的模型。唯一的要求是UserVote.created_byperform_create() 方法中自动设置。失败并出现以下异常:

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

我猜是因为 unique_together 索引。

models.py:

class UserVote(models.Model):
    created_by = models.ForeignKey(User, related_name='uservotes')
    rating = models.ForeignKey(Rating)

    class Meta:
        unique_together = ('created_by', 'rating')

序列化器.py

class UserVoteSerializer(serializers.ModelSerializer):
    id = serializers.IntegerField(read_only=True)
    created_by = UserSerializer(read_only=True)

    class Meta:
        model = UserVote
        fields = ('id', 'rating', 'created_by')

views.py

class UserVoteViewSet(viewsets.ModelViewSet):
    queryset = UserVote.objects.all()
    serializer_class = UserVoteSerializer
    permission_classes = (IsCreatedByOrReadOnly, )

    def perform_create(self, serializer):
        serializer.save(created_by=self.request.user)

如何在不让用户提供created_by 而是在代码中自动设置此字段的情况下将我的模型保存在 DRF 中?

提前致谢!

【问题讨论】:

    标签: python django database django-rest-framework unique


    【解决方案1】:

    以下代码对我有用。

    即使我在多次实验发现某些东西后也面临同样的错误,所以在类元中添加serializer.py中的所有字段,如下所示 -

    class Emp_UniSerializer( serializers.ModelSerializer ):
        class Meta:
            model = table
            fields = '__all__'  # To fetch For All Fields
            extra_kwargs = {'std_code': {'required': False},'uni_code': {'required': False},'last_name': {'required': False},'first_name': {'required': False}}
    

    在这里,我们可以更新"extra_kwargs"中的任何字段,它不会显示错误["This field is required."]

    【讨论】:

      【解决方案2】:

      我可以通过views.py 中的单行来解决这个问题

      def create(self, request, *args, **kwargs):
          request.data.update({'created_by': request.user.id})
          return super(UserVoteViewSet, self).create(request, *args, **kwargs)
      

      由于此视图希望用户通过身份验证,因此不要忘记将 permission_classes 扩展为 rest_framework.permissions.IsAuthenticated

      【讨论】:

      • 我收到This QueryDict instance is immutable 错误
      • @temirbek 根据docs,您可以使用QueryDict.copy()。希望对你有帮助
      【解决方案3】:

      你可以做的另一种奇怪的方法是使用这样的信号

      @receiver(pre_save, sender=UserVote)
      def intercept_UserVote(sender, instance, *args, **kwargs):
          import inspect
          for frame_record in inspect.stack():
              if frame_record[3]=='get_response':
                  request = frame_record[0].f_locals['request']
                  break
          else:
              request = None
      
          instance.pre_save(request)
      

      然后基本上你可以在你的模型中定义 pre_save

      def pre_save(self, request):
          # do some other stuff
          # Although it shouldn't happen but handle the case if request is None
          self.created_by = request.user
      

      这个系统的优点是您可以为每个模型使用相同的代码。如果您需要更改任何内容,只需更改 pre_save()。你也可以添加更多的东西

      【讨论】:

      • 检查堆栈?这是超级hacky。不要这样做。
      【解决方案4】:

      我遇到了类似的问题,我通过显式创建新实例并将其传递给序列化程序来解决它。在UserVoteViewSet 中,您必须将perform_create 替换为create

       def create(self, request, *args, **kwargs):
          uv = UserVote(created_by=self.request.user)
          serializer = self.serializer_class(uv, data=request.data)
          if serializer.is_valid():
              serializer.save()
              return Response(serializer.data, status=status.HTTP_201_CREATED)
          else:
              return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
      

      【讨论】:

      • 这很好!奇迹般有效!非常感谢您的提示!
      猜你喜欢
      • 1970-01-01
      • 2015-07-22
      • 2015-12-05
      • 1970-01-01
      • 2013-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多