Django Rest Framework:手动填充字段的最佳方法

0 投票
1 回答
779 浏览
提问于 2025-04-27 23:45

考虑以下模型:

class Request(models.Model):
    user = models.ForeignKey('User', related_name='requests')

还有一个包含创建和更新功能的视图集:

class RequestViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):

我想在创建时设置用户,但在更新时不设置用户。

第一个解决方案:

class RequestViewSet(mixins.CreateModelMixin, mixins.UpdateModelMixin, viewsets.GenericViewSet):
    def pre_save(self, obj):
        create = False
        try:
            if not obj.user:
                create = True
        except ObjectDoesNotExist:
            create = True
        if create:
            obj.user = self.request.user

第二个解决方案使用了 restore_object:

class RequestSerializer(serializers.ModelSerializer):
    def restore_object(self, attrs, instance=None):
        create = not instance
        instance = super(RequestSerializer, self).restore_object(attrs, instance)
        if create:
            request = self.context['request']
            instance.user = request.user
        return instance

哪个更合逻辑呢?我倾向于选择第一个(除了 try/except 之外,我找不到其他替代方案)。

暂无标签

1 个回答

1

我不是很喜欢基于类的视图,我更喜欢模型比较复杂,而视图比较简单。

我会选择在请求(Request)上使用一个post_save信号,并检查创建的参数。

https://docs.djangoproject.com/en/dev/ref/signals/#post-save

Request(...):
    @classmethod
    def post_save(cls, sender, instance, created, raw, **kwargs):
        if raw:
            return
        if created:
            pass  # do your on create stuff here

post_save.connect(Request.post_save, sender=Request, dispatch_uid="uniqueid")  # use weak=False if you use a local function

另外要注意的是,instance.save()会再次触发保存信号,所以如果你想避免再次处理所有信号(或者更糟糕的是,产生信号循环 ;-)),你可以考虑直接使用.update()。

撰写回答