![](/img/trans.png)
[英]Django-Rest-Framework: How to post to foreignkey field using request.user for logged in user
[英]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中)中。 你們知道我該如何實現嗎?
謝謝
我可以想到兩種方法來實現這一目標。
如果您只需要.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') # ...
獲取整個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.