gpt4 book ai didi

Django:使用 ForeignKey 注释对象的计数/总和 - 错误输出

转载 作者:行者123 更新时间:2023-11-29 13:53:31 25 4
gpt4 key购买 nike

我有设置了外键的模型:

STATUS = Choices('active', 'inactive', 'deleted')

class Project(models.Model):
status = models.CharField(
choices=STATUS,
default=STATUS.active,
max_length=20
)
objects = ProjectManager()

def delete(self):
self.status = STATUS.deleted
self.save()

class Observation(models.Model):
status = models.CharField(
choices=STATUS,
default=STATUS.active,
max_length=20
)
location = models.ForeignKey(
Location, related_name='locations'
)
project = models.ForeignKey(
Project, related_name='observations'
)
history = HistoricalRecords()
objects = ObservationManager()

def delete(self):
self.status = STATUS.deleted
self.save()

class Comment(models.Model):
status = models.CharField(
choices=STATUS,
default=STATUS.active,
max_length=20
)
commentto = models.ForeignKey(
Observation, related_name='comments'
)
objects = CommentManager()

def delete(self):
self.status = STATUS.deleted
self.save()

如您所见,可以更改对象的状态。此外,还有一种状态称为“已删除”。因此,我没有删除实际对象,而是将状态设置为“已删除”,然后管理器负责处理其余部分(返回除已删除项目外所需的所有内容)。

在 View 中,我想返回所有项目,但总共有一些观察和评论(每个项目)。另外,因为有数百个项目,所以我想尽可能地减少查询。

所以我最终得到了这个解决方案:

Project.objects.all().annotate(
observations_count=Sum(
Case(
When(
~Q(observations__status='deleted') &
Q(observations__isnull=False),
then=1
),
default=0,
output_field=IntegerField()
),
distinct=True
),
comments_count=Sum(
Case(
When(
~Q(observations__status='deleted') &
~Q(observations__comments___status='deleted') &
Q(observations__comments__isnull=False),
then=1
),
default=0,
output_field=IntegerField()
),
distinct=True
)
)

基本上,我想计算所有与“已删除”不同并且实际存在的观察结果,然后我对评论做同样的事情。

但是,这给了我错误的结果......

例如,如果我创建了一个观察和两个评论,然后我删除了一个评论,它将算作:2 个观察,1 个评论(这是完全错误的)。

或者如果我添加两个观察,一个有两个评论,但删除一个评论,另一个有一个评论但删除那个观察,它会给我:2 个观察,1 个评论。

现在如果我这样做:

projects = Project.objects.all()

for project in projects:
observations = project.observations.all()
project.observations_count = len(observations)
project.comments_count = Comment.objects.filter(commentto=observations).count()

它给了我正确的结果。但是,很明显,这对许多 SQL 查询造成了 waaaaayy,对我来说没有好处。

有人可以给我任何关于如何尝试解决这个问题的建议吗?

我寻求的解决方案......

所以我无法以任何方式让它工作......最终像这样解决它:

我将新字段 num_comments = models.IntegerField(default=0) 添加到观察模型,每次添加/删除评论时都会更新。然后我设法像这样正确计算所有内容:

Project.objects.all().annotate(
observations_count=Sum(
Case(
When(
~Q(observations__status='deleted') &
Q(observations__isnull=False),
then=1
),
default=0,
output_field=IntegerField()
),
distinct=True
),
comments_count=Sum(
Case(
When(
~Q(observations__status='deleted') &
Q(observations__isnull=False),
then='observations__num_comments'
),
default=0,
output_field=IntegerField()
),
distinct=True
)
)

这不是我一开始要去的地方,但可以完成工作...无论如何,如果有人有更好的解决方案,请不要犹豫,在下面留言。

最佳答案

这很棘手。你能试试下面吗,

projects = Project.objects.\
exclude(observations__status='deleted', observations__comments___status='deleted').\
filter(observations__status__isnull=False, observations__comments___status__isnull=False).\
annotate(count_observations=Count('observations__id'), count_comments=Count('observations__comments__id'))

你应该得到计数,

for p in projects:
print p.count_observations
print p.count_comments

更新:

实际上上面的查询不会按要求工作。所以我想这必须分两步完成。请尝试以下,

projects = Project.objects.\
exclude(observations__status='deleted').\
filter(observations__status__isnull=False).\
annotate(count_observations=Count('observations__id'))

projects = projects.\
exclude(observations__comments___status='deleted').\
filter(observations__comments___status__isnull=False).\
annotate(count_comments=Count('observations__comments__id'))

for p in projects:
print p.count_observations
print p.count_comments

关于Django:使用 ForeignKey 注释对象的计数/总和 - 错误输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36428366/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com