[英]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.