首页 > 解决方案 > DRF:正确使用序列化器和视图集的理论方法

问题描述

我喜欢 Python 和 Django,过去几周我一直在学习 Django REST 框架,因为在 2020 年的今天,没有人可以逃到 REST。在我的爱好项目中(这是一个 Python 论坛,可笑地称为 Pyrty,因为它是一个 Python派对),我决定为comments应用程序制作一个 CRUD。我做到了(通过更新除外),但我不明白将代码放入序列化程序和/或视图集中有什么区别。

My createandlist在序列化器中,而delete在 ViewSet 中。所有这些都按预期工作,但我不想编写脏代码,我希望了解将某些东西放在一个或另一个部分的重点和区别。

评论.models.py:

class Comment(PyrtyModel): # the inheritance class just adds creation and modification dates, and sorting stuff

    user = models.ForeignKey('users.User', on_delete=models.CASCADE, null=False)
    post = models.ForeignKey('posts.Post', on_delete=models.CASCADE, null=False)

    content = models.TextField(max_length=1000, null=False, blank=False)

    positive_votes = models.ManyToManyField('users.User', related_name='c_positive_vote_set')
    negative_votes = models.ManyToManyField('users.User', related_name='c_negative_vote_set')

    score = 0

    def __init__(self, *args, **kwargs):
        # init with the score (positive votes - negative votes) if the comment is persisted
        super(Comment, self).__init__(*args, **kwargs)
        if self.id is not None:
            self.score = (
                self.positive_votes.all().count() -
                self.negative_votes.all().count()
            )

    def __str__(self):
        """Return the comment str."""
        return "'{}'".format(self.content)

    class Meta(PyrtyModel.Meta):
        ordering = ['created', 'modified']

评论.serializers.py:

class CommentSerializer(serializers.ModelSerializer):
    """Comment model serializer."""

    user = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = Comment
        fields = '__all__'

    def create(self, validated_data):
        """Create a new comment in some post, by request.user."""

        validated_data['user'] = self.context['request'].user
        return super().create(validated_data)

    def list(self, request):
        """List all the comments from some post."""

        if 'post' not in request.query_params:
            raise ValidationError('Post id must be provided.')

        q = self.queryset.filter(post=request.query_params['post'])
        serializer = CommentSerializer(q, many=True)
        return Response(serializer.data)

评论.views.py:

class CommentViewSet(viewsets.ModelViewSet):

    serializer_class = CommentSerializer
    queryset = Comment.objects.all()

    def get_permissions(self):
        permissions = []
        if self.action == 'create' or self.action == 'destroy':
            permissions.append(IsAuthenticated)
        return [p() for p in permissions]

    def get_object(self):
        """Return comment by primary key."""
        return get_object_or_404(Comment, id=self.kwargs['pk'])

    def destroy(self, request, *args, **kwargs):
        """Delete a comment created by request.user from a post."""

        instance = self.get_object()
        if instance.user != request.user:
            raise ValidationError('Comment does not belong to the authenticated user.')
        self.perform_destroy(instance)
        run_reputation_update(request.user)
        return Response(status=status.HTTP_204_NO_CONTENT)

    def retrieve(self, request, pk=None):
        pass

    def update(self, request, pk=None):
        pass

    def partial_update(self, request, pk=None):
        pass

我应该在哪里以及何时将代码放在其中的一部分?

标签: pythonpython-3.xdjangorestdjango-rest-framework

解决方案


序列化器用于验证请求数据(传入参数)并格式化(序列化)数据以作为响应返回。

此外,序列化程序具有类似的方法,create您可以在其中定义应如何保存已验证数据的逻辑。这对于 ModelSerilizers 来说尤其方便。updatesave

所有其他逻辑都应在视图/视图集中定义。

我很确定你list在你的方法CommentSerializer没有做任何事情。因为序列化程序没有list方法,你在那里定义了它,但它从未使用过。ModelViewSet另一方面有list方法,我很确定这是您获取评论列表时使用的list方法,而不是序列化程序中的方法。


推荐阅读