用于ContentType对象的DRF序列化器返回null

时间:2019-11-15 16:36:59

标签: django django-rest-framework django-generic-views

我尝试使用ContentTypes Framework和DRF。我已阅读generic relationships

文档

我已经形成了BlogPost模型:

class BlogPost(models.Model):
    user = models.ForeignKey(User, default=1, null=True, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    comments = GenericRelation(Comment)

Comment型号:

class Comment(models.Model):
    comment_author = models.ForeignKey(User, default=1, null=True, on_delete=models.CASCADE)
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

我组成了serializers

class CommentSerializer(serializers.ModelSerializer):

    class Meta:
        model = Comment
        fields = "__all__"

​
class CommentedObjectRelatedField(serializers.RelatedField):
​
    def to_representation(self, value):
        """
        Serialize tagged objects to a simple textual representation.
        """
        if isinstance(value, Comment):
            serializer = CommentSerializer(value)
        else:
            raise Exception('Unexpected type of commented object')
        return serializer.data

class BlogPostSerializer(serializers.HyperlinkedModelSerializer):
    comments = CommentedObjectRelatedField(many=True, read_only=True)
    time_since_publication = serializers.SerializerMethodField()
​
​
    def get_time_since_publication(self, object):
        publication_date = object.published_at
        now = datetime.now()
        time_delta = timesince(publication_date, now)
        return time_delta
​
    class Meta:
        model = BlogPost
        fields = ['id', 'pk', 'title', 'slug', 'content','comments', 'published_at', 'timestamp', 'updated',  'time_since_publication']
        read_only_fields = ('pk',)
        lookup_field = ('pk',)
​    ​

当我在浏览器中检查api时,我会得到json答案

[
    {
        "id": 1,
        "pk": 1,
        "title": "this is title",
        "slug": "this-is-title",
        "content": "This is content",
        "comments": null,
        "published_at": "2019-11-15",
        "timestamp": "2019-11-15T12:14:37.336170Z",
        "updated": "2019-11-15T12:14:37.336208Z",
        "time_since_publication": "16 hours, 5 minutes"
    }
]

如何获得相关评论。 谢谢

ps:这是我的视图函数

class BlogPostListCreateAPIView(generics.ListCreateAPIView):
    queryset = BlogPost.objects.all()
    serializer_class = BlogPostSerializer

    def post(self, request, *args, **kwargs):
        title = request.data['title']
        self.slug = slugify(title)
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

class CommentListCreateAPIView(generics.ListCreateAPIView):
    queryset = BlogPost.objects.all()
    serializer_class = BlogPostSerializer

    def perform_create(self, serializer):
        blogpost_pk = self.kwargs.get("pk")
        blogpost = get_object_or_404(BlogPost, pk=pk)
        serializer.save()

class CommentDetailAPIView(generics.RetrieveUpdateDestroyAPIView):
    queryset = BlogPost.objects.all()
    serializer_class = BlogPostSerializer

1 个答案:

答案 0 :(得分:0)

好像您已切换通用关系和反向通用关系。在您引用的示例中,要序列化的对象是TaggedItem,这是具有通用外键的模型。但是在您的代码中,您尝试序列化一个BlogPost对象(即关系的另一面)的GenericRelation对象。从文档中:

  

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

尝试简单地从序列化程序中删除CommentedObjectRelatedField行。让HyperlinkedModelSerializer处理关系。

更新

在一个粗略的本地尝试中,将字段留在外面是行不通的(在这种情况下,我得到一个异常,指出“ GenericRelatedObjectManager类型的对象不可JSON序列化”)。我必须在序列化器中明确添加一个HyperlinkedRelatedField