【问题标题】:Django rest framework populate fields of nested objects programmaticallyDjango rest 框架以编程方式填充嵌套对象的字段
【发布时间】:2014-03-03 09:46:48
【问题描述】:

当需要在 Django Rest Framework 中以编程方式填充字段时,可以在 APIView 中覆盖 pre_save 方法,并且可以在那里填充所需的字段,例如:

def pre_save(self, obj):
    obj.owner = self.request.user

这对平面对象非常有效,但在嵌套情况下,嵌套对象无法在pre_save 方法中访问。到目前为止,我发现的唯一解决方案是重写 save_object 方法,并检查对象是否是嵌套类的实例,如果是,则在那里填充该字段。虽然这可行,但我不喜欢这个解决方案,想知道是否有人找到了更好的方法?

演示情况:

class Notebook(models.Model):
    owner = models.ForeignKey(User)

class Note(models.Model):
    owner = models.ForeignKey(User)
    notebook = models.ForeignKey(Notebook)
    note = models.TextField()

class NoteSerializer(serializers.ModelSerializer):
    owner = serializers.Field(source='owner.username')
    class Meta:
        model = Note
        fields = ('note', 'owner')

class NotebookSerializer(serializers.ModelSerializer):
    notes = NoteSerializer(many=True)
    owner = serializers.Field(source='owner.username')
    class Meta:
        model = Notebook
        fields = ('notes', 'owner')

    def save_object(self, obj, **kwargs):
        if isinstance(obj, Note):
            obj.owner = obj.notebook.owner

        return super(NotebookSerializer, self).save_object(obj, **kwargs)

class NotebookCreateAPIView(CreateAPIView):
    model = Notebook
    permission_classes = (IsAuthenticated,)
    serializer_class = NotebookSerializer

    def pre_save(self, obj):
        obj.owner = self.request.user

在问我为什么不使用不同的端点分别创建笔记本和笔记之前,让我说我这样做了,但我还需要一个功能来提供创建笔记本时的初始笔记,所以这就是我需要这个的原因也是一种端点。

另外,在我想出这个骇人听闻的解决方案之前,我实际上预计我将不得不重写 NoteSerializer 类本身的 save_object 方法,但事实证明,在嵌套对象的情况下,它甚至不会对于所有嵌套对象,只调用根对象的save_objects 方法,但我想这是一个设计决定。

再一次,这是否可以用更惯用的方式解决?

【问题讨论】:

    标签: python django django-rest-framework


    【解决方案1】:

    您可以在序列化程序上下文中访问请求。

    所以我的处理方法是:

    class NoteSerializer(serializers.ModelSerializer):
        owner = serializers.Field(source='owner.username')
    
        def restore_object(self, attrs, instance=None):
            instance = super(NoteSerializer, self).restore_object(attrs, instance)
            instance.owner = self.context['request'].user
            return instance
    
        class Meta:
            model = Note
            fields = ('note', 'owner')
    

    NotebookSerializer 也是如此。

    序列化器上下文将可用于ViewSet 中所有使用的序列化器。

    【讨论】:

    • 该死,这看起来不错,我会试试这个并回复你,谢谢直到那时
    猜你喜欢
    • 2014-05-21
    • 2020-11-07
    • 2012-11-02
    • 1970-01-01
    • 2019-06-14
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多