簡體   English   中英

Django(django-rest-framework)尋找最佳實踐,以找出進一步的request.user存在於blog.likes中

[英]Django (django-rest-framework) looking for a best practice to find out wether request.user exists in blog.likes

為了簡單起見,可以說我在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"

我正在尋找一種“最佳做法”的方式來:

  • 獲取所有博客
  • 為每個博客添加一個布爾值標志,指示我作為用戶是否喜歡該帖子。

有效率的!

我的直覺使我想像這樣實現它(使用基於類的通用視圖)

// views.py
class BlogPostList(ListAPIView):
    queryset = BlogPost.objects.all()
    serializer_class = BlogPostSerializer

    def get(self, request, *args, **kwargs):
        user = request.user
        return super(BlogPostList, self).get(...)


// serializers.py
class BlogPostSerializer(serializer.ModelSerializer):
    user = someUserSerializer(read_only=True)
    likes = BlogPostLikesSerializer()
    class Meta:
        model = BlogPost
        fields = ("id", "user", "likes", "content", "image")

class BlogPostLikesSerializer(serializer.ModelSerializer):
    blogpost = BlogPostSerializer()
    user = SomeUserSerializer()
    class Meta:
        model = BlogPostLikes
        fields = ("id", "user", "blogpost", "timestamp")

但是后來我被困住了。 我不知道如何修改我的BlogPostLikesSerializer以指示當前用戶( views.py request.user )是否包含在喜歡的集合(如果BlogPost中)中。 你們知道我該如何實現嗎?

謝謝

我可以想到兩種方法來實現這一目標。

  1. 如果您只需要.extra boolean True / False無論request.user是否喜歡Post則可以使用.extra

    1.1。 將您的BlogPost Queryset BlogPost Queryset為以下內容:

     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方法

     class BlogPostList(ListAPIView): def get_queryset(self): user = self.request.user return BlogPost.objects.annotate_is_liked_by_user(user) 

    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) 

    並從BlogPostLikesSerializer刪除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})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM