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

相關問題