python Django REST框架:“此字段为必填字段,”,其中required=False和unique_together

fdx2calv  于 2023-01-19  发布在  Python
关注(0)|答案(5)|浏览(158)

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

{
    "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')

serializers.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)

如何在DRF中保存我的模型,而不需要用户提供created_by,而是在代码中自动设置此字段?
先谢了!

xwbd5t1u

xwbd5t1u1#

我也遇到过类似的问题,我通过显式创建一个新示例并将其传递给序列化器来解决它。在UserVoteViewSet中,必须用create替换perform_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)
gijlo24d

gijlo24d2#

我能够用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

xdyibdwo

xdyibdwo3#

另一个奇怪的方法是使用这样的信号

@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_保存

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()中改变。你也可以添加更多的东西

k5hmc34c

k5hmc34c4#

将以下内容添加到ViewSet

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

Serializer上还有以下代码:

class Meta:
    extra_kwargs = {
        'user': {
            'required': False,
        },
    }
wn9m85ua

wn9m85ua5#

下面的代码对我有效。
即使是我也面临着同样的错误,在许多实验后发现了一些东西,所以添加了类 meta中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."]

相关问题