4

GenericRelationDRF に 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')

コメントアウトされた 2 つの行は、DRF にvoteable内部でシリアル化する方法を伝える私の試みQuestion
です。

'GenericRelatedObjectManager' object has no attribute 'pk'

そして2番目

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

だから、明らかに私は何かを誤解しています。

4

3 に答える 3

2

GenericRelation により適していると思われるソリューションの代替案...

  • Voteable を抽象モデルにする
  • 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')

おそらくより最適ですが、継承するオブジェクトのタイプごとに個別の「投票」クラスを持つ方がDRYが少なくなります。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')
于 2015-12-30T02:12:07.603 に答える