我想在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
- 将
VoteableSerializer
从HyperlinkedModelSerializer
更改为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')
...