Django Rest Framework ModelSerializer在创建时设置属性 [英] Django Rest Framework ModelSerializer Set attribute on create

查看:636
本文介绍了Django Rest Framework ModelSerializer在创建时设置属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最初创建对象时,我使用当前登录的用户分配模型字段owner。

When creating an object initially I use the currently logged-in user to assign the model field 'owner'.

模型:

class Account(models.Model):

    id = models.AutoField(primary_key=True)
    owner = models.ForeignKey(User)
    name = models.CharField(max_length=32, unique=True)
    description = models.CharField(max_length=250, blank=True)

序列化器设置所有者:

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Account
        fields = ('name', 'description')

    def restore_object(self, attrs, instance=None):
        instance = super().restore_object(attrs, instance)

        request = self.context.get('request', None)
        setattr(instance, 'owner', request.user)

        return instance

是p对于我的系统中的其他用户来说,可以更新另一个帐户对象,但所有权应与原始用户保持一致。显然,以上打破了这一点,因为当前登录的用户更新时,所有权将被覆盖。

It is possible for a different user in my system to update another's Account object, but the ownership should remain with the original user. Obviously the above breaks this as the ownership would get overwritten upon update with the currently logged in user.

所以我更新了这样:

class AccountSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Account
        fields = ('name', 'description')

    def restore_object(self, attrs, instance=None):
        new_instance = False
        if not instance:
            new_instance = True

        instance = super().restore_object(attrs, instance)

        # Only set the owner if this is a new instance
        if new_instance:
            request = self.context.get('request', None)
            setattr(instance, 'owner', request.user)

        return instance

这是推荐的方式来做这样的事情吗?我看不到任何其他方式,但我迄今为止的经验非常有限。

Is this the recommended way to do something like this? I can't see any other way, but I have very limited experience so far.

谢谢

从回顾@ zaphod100.10的答案。或者,在视图代码中(删除了上述序列化程序中的自定义restore_object方法):

From reviewing @zaphod100.10's answer. Alternatively, in the view code (with custom restore_object method in above serializer removed):

def post(self, request, *args, **kwargs):

    serializer = self.get_serializer(data=request.DATA, files=request.FILES)

    if serializer.is_valid():
        serializer.object.owner = request.user
        self.pre_save(serializer.object)
        self.object = serializer.save(force_insert=True)
        self.post_save(self.object, created=True)
        headers = self.get_success_headers(serializer.data)

        return Response(serializer.data, status=status.HTTP_201_CREATED,
                        headers=headers)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


推荐答案

基本上,您希望所有者在创建时设置,而不是后续更新。为此,我认为您应该在POST视图中设置所有者。我认为这样更合乎逻辑和鲁棒。通过PUT视图进行更新,因此您的数据应始终是正确的,因为如果所有者在PUT上不可编辑,则无法更新所有者。

Basically you want the owner to be set on creation and not on subsequent updates. For this I think you should set the owner in the POST view. I think it is more logical and robust that way. Update is done via PUT view so your data should always be correct since no way on updation the owner can be changed if the owner is not editable on PUT.

视图可以使用DRF的泛型类视图。使用RetrieveUpdateDeleteView原样。对于ListCreateView覆盖post方法。使用django模型表单验证数据并创建一个帐户实例。

For making the views you can use DRF's generic class based views. Use the RetrieveUpdateDeleteView as it is. For ListCreateView override the post method. Use a django model form for validating the data and creating an account instance.

您将不得不复制request.DATA dict并将owner作为当前用户。

You will have to copy the request.DATA dict and insert 'owner' as the current user.

POST方法的代码可以是:

The code for the POST method can be:

def post(self, request, *args, **kwargs):
    data = deepcopy(request.DATA)
    data['owner'] = request.user
    form = AccountForm(data=data)
    if form.is_valid():
        instance = form.save(commit=false)
        instance.save()
        return Response(dict(id=instance.pk), status=status.HTTP_201_CREATED)
    return Response(form.errors, status=status.HTTP_400_BAD_REQUEST)

这篇关于Django Rest Framework ModelSerializer在创建时设置属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆