如何在Django Rest框架中使用GenericRelation



我想在DRF 中包含一个具有GenericRelation反向参考的模型

文件表明这应该很容易(就在上面:http://www.django-rest-framework.org/api-guide/relations/#manytomanyfields-有一个直通模型)-但我错过了一些东西!

请注意,反转泛型键,使用GenericRelation表示字段可以使用常规关系字段类型进行序列化,因为关系中的目标的类型总是已知的。

有关更多信息,请参阅关于泛型的Django文档关系

我的型号:

class Voteable(models.Model):
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    direct_vote_count = models.IntegerField(default=0)
class Question(models.Model):
    user = models.ForeignKey(UserExtra, related_name='questions_asked')
    voteable = GenericRelation(Voteable)
    question = models.CharField(max_length=200)

和我的序列化程序:

class VoteableSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Voteable
        fields = ('pk', 'id', 'url', 'direct_vote_count')

class QuestionSerializer(serializers.HyperlinkedModelSerializer):
    #voteable = VoteableSerializer(read_only=True, many=False)
    #voteable = serializers.PrimaryKeyRelatedField(many=False, read_only=True)
    class Meta:
        depth = 1
        model = Question
        fields = ('url', 'question', 'user', 'voteable')

这两行注释是我试图告诉DRF如何在Question中序列化voteable
第一个给了我

'GenericRelatedObjectManager' object has no attribute 'pk'

和第二个

<django.contrib.contenttypes.fields.create_generic_related_manager.<locals>.GenericRelatedObjectManager object at 0x7f7f3756cf60> is not JSON serializable

所以,很明显我误解了什么,知道吗?

好吧,我有一个有效的解决方案,尽管它感觉不是正确的解决方案。。。。

class VoteableSerializer(serializers.ModelSerializer):
    class Meta:
        model = Voteable
        fields = ('pk', 'direct_vote_count')

class VoteableRelatedField(serializers.RelatedField):
    def to_representation(self, value):
        serializer = VoteableSerializer(value.get_queryset()[0])
        return serializer.data
class QuestionSerializer(serializers.HyperlinkedModelSerializer):
    #voteable = VoteableSerializer(read_only=True, many=False)
    #voteable = serializers.PrimaryKeyRelatedField(many=False, read_only=True)
    voteable = VoteableRelatedField(read_only=True)
    class Meta:
        depth = 1
        model = Question
        fields = ('url', 'question', 'user', 'voteable')
        read_only_fields = ('voteable',)
  • VoteableSerializer中删除url
  • VoteableSerializerHyperlinkedModelSerializer更改为ModelSerializer
  • 添加VoteableRelatedField并从查询集中获取第一个项目(这感觉特别错误)

我还不会将其标记为已接受,希望有人能启发我如何

解决方案的另一个想法,似乎更适合GenericRelation。。。

  • 使可投票成为一个抽象模型
  • 更改Vote类(此问题中未显示)以使用GenericForeignKey指向任何内容

优点:
这意味着投票信息总是正确的在相关对象上,简化了排序&查询和避免联接。

缺点:
投票需要更多的空间

class Voteable(models.Model):
    votes = GenericRelation(Vote)
    direct_vote_count = models.IntegerField(default=0)
    class Meta:
        abstract = True
class Question(Voteable):
    user = models.ForeignKey(UserExtra, related_name='questions_asked')
    question = models.CharField(max_length=200)
class Vote(models.Model):
    user = models.ForeignKey(UserExtra, related_name='questions_asked')
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

对于继承Voteable 的每种类型的对象,可能有一个单独的"Vote"类更为优化,但DRY更少

class Voteable(models.Model):
    direct_vote_count = models.IntegerField(default=0)
    class Meta:
        abstract = True
class Question(Voteable):
    user = models.ForeignKey(UserExtra, related_name='questions_asked')
    question = models.CharField(max_length=200)
class QuestionVote(models.Model):#This class also repeated for each item that can be voted on
    user = models.ForeignKey(UserExtra, related_name='questions_asked')
    parent = models.ForeignKey(Question, related_name='votes')

文档似乎不需要自定义相关的序列化程序字段。GenericRelation:有这个脚注

请注意,反转泛型键,使用GenericRelation表示字段可以使用常规关系字段类型进行序列化,因为关系中的目标的类型总是已知的。

下面的应用程序。同时检查此DRF3扩展。

class QuestionSerializer(serializers.HyperlinkedModelSerializer):
    voteable = VoteableSerializer(read_only=True)
    class Meta:
        model = Question
        fields = ('url', 'question', 'user', 'voteable')
        ...

相关内容

  • 没有找到相关文章

最新更新