Django - 一对多关系中的否定查询
Django - negative query in one-to-many relationship
鉴于这些模型:
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)
给定一个个人资料,我想查找由该个人资料创建的所有博客 post,其中要么没有评论,要么只有 post 的创建者] 发表了评论。
例如:
profile = Profile.objects.get(id={id})
profile.posts.exclude(~Q(comments__created_by=profile))
我认为 .exclude(~Q(comments__created_by=profile) 会排除所有存在评论的 posts,这些评论是由个人资料以外的其他人创建的,但这是行不通的.(它发现 posts 其中 created_by 为空,并且 posts 其中配置文件与其他用户一起评论 - 我试图从集合中排除)
好吧,您差不多已经完成了,只需要根据您的直觉添加条件。解决此问题的一个好方法是使用 django shell 和一堆与您的排列匹配的测试数据。对于更复杂的查询,最好先编写单元测试。
profile.posts.filter(Q(comments__isnull=True)|~Q(comments__created_by=profile, comments__created_by__isnull=False))
您需要的是:
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))
鉴于这些模型:
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)
给定一个个人资料,我想查找由该个人资料创建的所有博客 post,其中要么没有评论,要么只有 post 的创建者] 发表了评论。
例如:
profile = Profile.objects.get(id={id})
profile.posts.exclude(~Q(comments__created_by=profile))
我认为 .exclude(~Q(comments__created_by=profile) 会排除所有存在评论的 posts,这些评论是由个人资料以外的其他人创建的,但这是行不通的.(它发现 posts 其中 created_by 为空,并且 posts 其中配置文件与其他用户一起评论 - 我试图从集合中排除)
好吧,您差不多已经完成了,只需要根据您的直觉添加条件。解决此问题的一个好方法是使用 django shell 和一堆与您的排列匹配的测试数据。对于更复杂的查询,最好先编写单元测试。
profile.posts.filter(Q(comments__isnull=True)|~Q(comments__created_by=profile, comments__created_by__isnull=False))
您需要的是:
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))