如果在另一个 table 中存在一行,则添加一个布尔字段?
Add a boolean field if a row exists in another table?
我有两个表 Post
和 Reply
。用户只能为每个 Post
创建一个 Response
。模型如下所示:
class Post(models.Model):
name = models.CharField(max_length = 100)
class Reply(models.Model):
post = models.ForeignKey(Post, related_name = 'replies')
现在,我认为 returns post 是这样的:
class PostList(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticated,)
queryset = Post.objects.all()
serializer_class = PostSerializer
以及 post 的序列化程序:
class PostSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'name')
此视图的结果如下所示:
[
{
"id": "1",
"name": "The first post"
},
{
"id": "2",
"name": "The second post"
}
]
现在,对于所讨论的实际问题:如果用户已回复 post,我希望在结果中有一个布尔字段 true
,并且 false
如果他们没有。基本上,当前用户回复了第一个 post 但没有回复第二个 post 的情况的结果将如下所示:
[
{
"id": "1",
"name": "The first post",
"replied": "true"
},
{
"id": "2",
"name": "The second post",
"replied": "false"
}
]
我该如何实现?我有一种预感,这应该以某种方式在序列化程序中实现,但我不知道该怎么做。
在此先感谢您的帮助!
这里的下一个问题是许多 sql 查询,当您将获取例如。 100 个对象(您将有 BASE_QUERIES_COUNT + len(objects) )。当然,我们不希望线性 sql 查询计数,这种情况
永远不应该发生,尤其是在生产版本中。完美的
这里的解决方案是,如果我们能够获取所有数据
一个 sql 查询。这可以通过覆盖 get_queryset
方法(这里是 https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/generics.py#L47 )实现。然后 queryset 可能如下所示,param current_user_replies_count
可用作普通模型实例变量。
# all only for example
Post.objects.all().extra(select={
'current_user_replies_count': 'SELECT COUNT(*) FROM <reply table> WHERE '+
'post_id=posts_post.id AND owner_id = %s'
},
select_params=(request.user.id,)
)
我还没有测试过,所以更多地使用它作为示例而不是现成的解决方案,
你应该将 current_user_replies_count 转换为 bool.
在这里借用 dydek 的回答。
您在 Api 视图
中覆盖了您的 get_queryset
class PostList(generics.ListAPIView):
...
def get_queryset(self):
Post.objects.all().extra(select={
'current_user_replies_count': 'SELECT COUNT(*) FROM <reply table> WHERE' +
'post_id=posts_post.id AND owner_id = %s'
},select_params=(request.user.id,))
这会将 'current_user_replies_count' 作为 属性 添加到查询集中的 Post 对象。
您可以将自定义字段添加到 PostSerializer
class PostSerializer(serializers.ModelSerializer):
replied = serializers.SerializerMethodField('has_replies')
def has_replies(post):
return post.replies.filter(owner=self.context["request"].user).exists()
class Meta:
fields = ('id', 'name', 'replied')
我有两个表 Post
和 Reply
。用户只能为每个 Post
创建一个 Response
。模型如下所示:
class Post(models.Model):
name = models.CharField(max_length = 100)
class Reply(models.Model):
post = models.ForeignKey(Post, related_name = 'replies')
现在,我认为 returns post 是这样的:
class PostList(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticated,)
queryset = Post.objects.all()
serializer_class = PostSerializer
以及 post 的序列化程序:
class PostSerializer(serializers.ModelSerializer):
class Meta:
fields = ('id', 'name')
此视图的结果如下所示:
[
{
"id": "1",
"name": "The first post"
},
{
"id": "2",
"name": "The second post"
}
]
现在,对于所讨论的实际问题:如果用户已回复 post,我希望在结果中有一个布尔字段 true
,并且 false
如果他们没有。基本上,当前用户回复了第一个 post 但没有回复第二个 post 的情况的结果将如下所示:
[
{
"id": "1",
"name": "The first post",
"replied": "true"
},
{
"id": "2",
"name": "The second post",
"replied": "false"
}
]
我该如何实现?我有一种预感,这应该以某种方式在序列化程序中实现,但我不知道该怎么做。
在此先感谢您的帮助!
这里的下一个问题是许多 sql 查询,当您将获取例如。 100 个对象(您将有 BASE_QUERIES_COUNT + len(objects) )。当然,我们不希望线性 sql 查询计数,这种情况
永远不应该发生,尤其是在生产版本中。完美的
这里的解决方案是,如果我们能够获取所有数据
一个 sql 查询。这可以通过覆盖 get_queryset
方法(这里是 https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/generics.py#L47 )实现。然后 queryset 可能如下所示,param current_user_replies_count
可用作普通模型实例变量。
# all only for example
Post.objects.all().extra(select={
'current_user_replies_count': 'SELECT COUNT(*) FROM <reply table> WHERE '+
'post_id=posts_post.id AND owner_id = %s'
},
select_params=(request.user.id,)
)
我还没有测试过,所以更多地使用它作为示例而不是现成的解决方案, 你应该将 current_user_replies_count 转换为 bool.
在这里借用 dydek 的回答。
您在 Api 视图
中覆盖了您的 get_querysetclass PostList(generics.ListAPIView):
...
def get_queryset(self):
Post.objects.all().extra(select={
'current_user_replies_count': 'SELECT COUNT(*) FROM <reply table> WHERE' +
'post_id=posts_post.id AND owner_id = %s'
},select_params=(request.user.id,))
这会将 'current_user_replies_count' 作为 属性 添加到查询集中的 Post 对象。
您可以将自定义字段添加到 PostSerializer
class PostSerializer(serializers.ModelSerializer):
replied = serializers.SerializerMethodField('has_replies')
def has_replies(post):
return post.replies.filter(owner=self.context["request"].user).exists()
class Meta:
fields = ('id', 'name', 'replied')