如果在另一个 table 中存在一行,则添加一个布尔字段?

Add a boolean field if a row exists in another table?

我有两个表 PostReply。用户只能为每个 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')