3

我想包括在DRF如何在Django Rest Framework中使用GenericRelation?

该文档与GenericRelation backrefrence的模型表明,这应该是很容易(略高于:http://www.django-rest-framework.org/api-guide/relations/#manytomanyfields-with-a-through-model) - 但我失去了一些东西!

注意,反向通用密钥,使用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如何序列尝试voteableQuestion
第一个给我

'GenericRelatedObjectManager' object has no attribute 'pk'

和第二

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

因此,很明显,我误解的东西,任何想法是什么?

+0

你想要实现的是通用的1对1关系。它不支持开箱即用。看看[这个问题](http://stackoverflow.com/q/7837330/1377864)可能的解决方法:'voteable = GenericRelation(Voteable)'成为'voteables = GenericRelation(可投票)'+'voteable'属性模型级别。用这种方法你的第一个选项应该可以正常工作 –

+1

我看到 - 我想我的另一种选择是使用指向可投票的常规ForeignKey(以及其他我想投票的类)而不是GenericRelation ... – Chozabu

回答

2

嗯,我有一个有效的解决方案,但它不觉得自己是正确的解决方案....

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',) 
  • urlVoteableSerializer
  • 变化VoteableSerializerModelSerializerHyperlinkedModelSerializer
  • 删除添加VoteableRelatedField并从查询集中获取第一项(特别感觉不对)

我不会将此标记为已接受,希望有人能启发我如何应该完成!解决的办法,这似乎更适合GenericRelation

+0

将此标记为已接受 - 因为它似乎是正确的回答问题标题。尽管如此,我的其他答案可能是对所描述的确切情况的更好解决方案。 – Chozabu

+1

这部分'value.get_queryset()[0]'正是我所需要的,但我同意它不觉得是最好的解决方案。 –

+0

很高兴听到我帮助!在我的项目中,我实际上最终没有使用GenericRelations,除非它们很重要,因为许多查询很难通过这种关系运行。当然,我有一个新的问题 - graphingDBs看起来越来越诱人... – Chozabu

2

另类的想法...

  • 让Voteable的抽象模型
  • 阿尔特投票类(在这个问题上未显示)使用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每种类型的对象的一个​​单独的“投票”类

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') 
0

定制相关的串行领域似乎不必要的doc有这个脚注Generi cRelation:

注意,反向通用密钥,使用GenericRelation 字段中表达,可以使用常规关系字段类型, 由于目标的关系中的类型总是已知的序列化。

以下申请。还请检查this DRF3扩展。

class QuestionSerializer(serializers.HyperlinkedModelSerializer): 
    voteable = VoteableSerializer(read_only=True) 

    class Meta: 
     model = Question 
     fields = ('url', 'question', 'user', 'voteable') 
     ... 
+0

我不再在这个项目上工作 - 但看着你的答案..我引用你引用的行 - 甚至尝试过解决方案你建议! (其中很多= false) – Chozabu

+0

虽然,您链接的扩展可能会完成所需的工作 - 而DRF有可能解决了一个问题,使我们的代码都可以正常工作 - 不幸的是我无法测试 – Chozabu

相关问题