Django - 一对多关系中的否定查询

时间:2015-03-02 01:32:54

标签: django django-queryset

鉴于这些模型:

class Profile(models.Model):
    name = models.CharField(max_length=50)

class BlogPost(models.Model):
    name = models.CharField(max_length=50)
    created_by = models.ForeignKey(Profile, related_name='posts')

class Comment(models.Model):
    blog = models.ForeignKey(BlogPost, related_name='comments')
    body_text = models.TextField()
    created_by = models.ForeignKey(Profile, null=True, blank=True, on_delete=models.SET_NULL)

鉴于个人资料,我想查找该个人资料所创建的所有博客帖子,其中既没有评论,也没有帖子的创建者评论过。

例如:

profile = Profile.objects.get(id={id})
profile.posts.exclude(~Q(comments__created_by=profile))

我认为.exclude(~Q(comments__created_by =个人资料)会排除所有发布评论的帖子,这些帖子是由个人资料以外的其他人创建的,但却没有成功。(它正在查找帖子created_by为null,并且还发布了个人资料与其他用户一起评论的位置 - 我试图从集合中排除这些用户

2 个答案:

答案 0 :(得分:1)

你需要的是:

comments_by_others_in_profile_posts = Comment.objects \
    .filter(blog__created_by=profile) \
    .exclude(created_by=profile)

profile.posts.exclude(comments=comments_by_others_in_profile_posts)

您也可以这样尝试(我相信这样可以加快一点,但需要查看EXPLAIN输出的查询):

profile.posts.exclude(id__in=comments_by_others_in_profile_posts.values_list('blog', flat=True))

答案 1 :(得分:0)

你几乎就在那里,只需要从你的直觉中包括条件。解决这个问题的一个好方法是使用django shell和一堆与你的排列相匹配的测试数据。对于更复杂的查询,首先编写单元测试是一个好主意。

profile.posts.filter(Q(comments__isnull=True)|~Q(comments__created_by=profile, comments__created_by__isnull=False))