【问题标题】:Serializing a generic relation in django-rest-framework序列化 django-rest-framework 中的通用关系
【发布时间】:2016-08-02 13:31:53
【问题描述】:

我正在尝试学习如何在 Django-Rest-Framework 中使用 GenericRelations。我找到了serializer relations 的文档页面并遵循了代码。 我创建了模型:

class TaggedItem(models.Model):
    """
    Tags arbitary model instance using a generic relation.

    """
    tag_name = models.SlugField()
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    tagged_object = GenericForeignKey('content_type', 'object_id')

    def __unicode__(self):
        return self.tag_name

class Bookmark(models.Model):
    """
    A bookmark consists of a URL, and 0 or more descriptive tags.
    """
    link_url = models.URLField()
    tags = GenericRelation(TaggedItem)

class Note(models.Model):
    """
    A note consists of some texts, and 0 or more descriptive tags
    """
    text = models.CharField(max_length=1000)
    tags = GenericRelation(TaggedItem)

我创建了序列化程序:

class BookmarkSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bookmark
        fields = ('url', 'link_url', )


class NoteSerializer(serializers.ModelSerializer):
    class Meta:
        model = Note
        fields = ('url', 'text', )


class TaggedObjectRelatedField(serializers.RelatedField):
    """
    A custom field to use for the 'tagged_object' generic relationship
    """

    def to_representation(self, value):
        """
        Serialize tagged objects to their respective serializer formats
        :param value:
        :return:
            serializer.data
        """
        if isinstance(value, Bookmark):
            return 'Bookmark: ' + value.url
        elif isinstance(value, Note):
            return 'Note: ' + value.text
        raise Exception('Unexpected type of tagged object')


class TaggedItemSerializer(serializers.ModelSerializer):
    tagged_object = TaggedObjectRelatedField()
    class Meta:
        model = TaggedItem
        fields = ('url', 'id', 'tag_name', 'tagged_object')

现在 TaggedItemSerializer 内的 TaggedObjectRelatedField() 的输入应该是什么? 目前我收到错误

  File "/home/aswin/Documents/WebProjects/drf_practice/uni_auth//loginpage/login/serializers.py", line 76, in TaggedItemSerializer
    tagged_object = TaggedObjectRelatedField()
  File "/home/aswin/Documents/WebProjects/drf_practice/uni_auth/lib/python3.5/site-packages/rest_framework/relations.py", line 80, in __init__
    'Relational field must provide a `queryset` argument, '
AssertionError: Relational field must provide a `queryset` argument, override `get_queryset`, or set read_only=`True`.

我也尝试将参数设置为 read_only=True,但它抛出了同样的错误。只是为了说明我所做的:

class TaggedItemSerializer(serializers.ModelSerializer):
    tagged_object = TaggedObjectRelatedField(read_only=True)

请帮我解决这个问题

【问题讨论】:

    标签: django serialization django-rest-framework


    【解决方案1】:

    我在你提到的关于序列化 TaggedItem 的文章中没有看到任何内容,你为什么要序列化 ​​TaggedItem?

    这是我的序列化程序类:

    from models import Bookmark, Note, TaggedItem
    from rest_framework import serializers
    
    
    class TaggedObjectRelatedField(serializers.RelatedField):
        def to_representation(self, value):
            if isinstance(value, Bookmark):
                serializer = BookMarkSerializer(value)
            elif isinstance(value, Note):
                serializer = NoteSerializer(value)
            else:
                raise Exception('Unexpected type of tagged object')
    
            return serializer.data
    
    
    class BookMarkSerializer(serializers.HyperlinkedModelSerializer):
        tags = TaggedObjectRelatedField(many=True, queryset=TaggedItem.objects.all())
    
        class Meta:
            model = Bookmark
            fields = ('pk', 'url', 'tags')
    
    
    class NoteSerializer(serializers.HyperlinkedModelSerializer):
        tags = TaggedObjectRelatedField(many=True, queryset=TaggedItem.objects.all())
    
        class Meta:
            model = Note
            fields = ('pk', 'text', 'tags')
    

    【讨论】:

    • DRF 文档中肯定缺少此代码 sn-p。会让事情变得更清楚。
    • 但是为什么不应该'想要序列化 ​​TaggedItem'。我认为序列化通用模型是一种完全有效的方法。这怎么可能做到?
    • 我刚试过这个方法,但它不再起作用了。 ModelSerializer 代替 HyperLinkedModelSerializer
    • 我收到local variable 'serializer' referenced before assignment 错误。由于序列化程序变量正在获取尚未分配的序列化程序。
    【解决方案2】:

    聚会有点晚了,但我想如果你想为TaggedItem 创建一个序列化程序,你可以签出rest-framework-generic-relations。因此,根据他们的文档,您可以创建如下内容:

    from generic_relations.relations import GenericRelatedField
    
    class TagSerializer(serializers.ModelSerializer):
        """
        A `TaggedItem` serializer with a `GenericRelatedField` mapping all possible
        models to their respective serializers.
        """
        tagged_object = GenericRelatedField({
            Bookmark: BookmarkSerializer(),
            Note: NoteSerializer()
        })
    
        class Meta:
            model = TaggedItem
            fields = ('tag_name', 'tagged_object')
    

    或类似:

    class TagSerializer(serializers.ModelSerializer):
        """
        A `Tag` serializer with a `GenericRelatedField` mapping all possible
        models to properly set up `HyperlinkedRelatedField`s.
        """
        tagged_object = GenericRelatedField({
            Bookmark: serializers.HyperlinkedRelatedField(
                queryset = Bookmark.objects.all(),
                view_name='bookmark-detail',
            ),
            Note: serializers.HyperlinkedRelatedField(
                queryset = Note.objects.all(),
                view_name='note-detail',
            ),
        })
    
        class Meta:
            model = TaggedItem
            fields = ('tag_name', 'tagged_object')
    

    【讨论】:

      猜你喜欢
      • 2015-12-13
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      • 2021-06-12
      • 1970-01-01
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      相关资源
      最近更新 更多