Django(Djangorestframework)正在寻找最佳实践来发现请求.用户存在于博客.likes

2024-10-03 00:28:05 发布

您现在位置:Python中文网/ 问答频道 /正文

为了简单起见,假设我在Django(Django rest framework)应用程序中有以下模型。在

User (id, name)

BlogPost (id, user, content, image)

BlogPostLikes(id, user, blogpost, timestamp) 
// Assuming an inverse-relation to BlogPost via a variable called "likes"

我正在寻找一种“最佳实践”方式:

  • 获取所有博客
  • 为每个blog添加一个boolean标志,指示作为用户的我是否喜欢这篇文章。在

效率高!在

我的直觉让我想这样实现它(使用基于类的通用视图)

^{pr2}$

但后来我被卡住了。我不知道如何修改我的BlogPostLikesSerializer以指示当前用户(request.user来自views.py)是否包含在博客文章的likes集中。你们知道我该怎么做吗?在

谢谢


Tags: django用户name模型imagerestid应用程序
2条回答

我可以想出两种方法来达到这个目的。在

  1. 如果您只需要一个booleanTrue/False是否喜欢Post,那么可以使用.extra。在

    1.1条。将您的BlogPostQueryset改为如下所示:

    class BlogPostQuerySet(models.QuerySet):
        def annotate_is_liked_by_user(self, user):
            return self.extra(
                select = {'is_liked': 'EXISTS( \
                    SELECT `id` FROM `blogpostlikes` \
                    WHERE `blogpostlikes`.`blogpost_id` = `blogpost`.id \
                    AND `blogpostlikes`.`user_id` = %s)' % user.id
                }
            )
    
    class BlogPost
        # other stuffs here
        objects = BlogPostQuerySet.as_manager()
    

    1.2条。在BlogPostList视图中更改get_queryset方法

    ^{pr2}$

    1.3条。将新字段添加到BlogPostSerializer

    class BlogPostSerializer(serializer.ModelSerializer):
        # ....
        is_liked = serializers.BooleanField(source='is_liked')
        # ...
    
  2. 获取整个BlogPostLike对象。在

    2.1.更改get_queryset方法。在

    class BlogPostList(ListAPIView):
    
        def get_queryset(self):
            user = self.request.user
            return BlogPost.objects.prefetch_related(
                Prefetch(
                    'likes', 
                    queryset=BlogPostLikes.objects.filter(user=user) \
                        .select_related('user'), 
                    to_attr='likes_by_request_user'
                )
            )
    

    2.2条。改变serializer。但这可以通过两种方式实现:

    2.2.1条。序列化包含一项的列表:

    class BlogPostSerializer(serializer.ModelSerializer):
        # ...
        likes_by_request_user = BlogPostLikesSerializer(many=True)
    

    并从^{中删除blogpost = BlogPostSerializer()。我认为这会导致无限循环。在

    2.2.2序列化单个对象:

    class BlogPostSerializer(serializer.ModelSerializer):
        # ...
        like_by_request_user = BlogPostLikesSerializer(source='get_last_like', required=False)
    

    但是通过这种方式,您必须在BlogPost对象中添加一个新方法来返回这个Like对象

    class BlogPost(models.Model):
        #...
        def get_last_like(self):
            if hasattr(self, 'likes_by_request_user') and len(self.likes_by_request_user) > 0:
                return self.likes_by_request_user[0]
            return None
    

可以使用SerializerMethodField动态获取标志,如下所示:

class BlogPostSerializer(serializer.ModelSerializer):
    user = SomeUserSerializer()
    likes = BlogPostLikesSerializer()
    has_liked = SerializerMethodField("get_has_liked")
    class Meta:
        model = BlogPostLikes
        fields = ("id", "user", "likes", "content", "image", "has_liked")

    def get_has_liked(self, obj):
        user = self.context.get('request').user
        return len([l.user.id == user.id for l in obj.likes]) > 0

但是,您需要在实例化序列化程序时传递请求,方法是执行以下操作:serializer = BlogPostSerializer(context={'request': request})

相关问题 更多 >