我有三个模型,简化为例子:
class Customer(models.Model):
email = models.CharField(max_length=128)
class Order(models.Model):
customer = models.ForeignKey(Customer)
order_status = models.CharField(blank=True, max_length=256)
class Lineitem(models.Model):
order = models.ForeignKey(Order)
quantity = models.IntegerField(blank=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
Run Code Online (Sandbox Code Playgroud)
我想查询客户(可能使用过滤器)并注释他们花费的总额(即总和(价格*数量))
我试过了:
Customer.objects.filter(something).annotate(total_spent=Sum(F('order__lineitem__quantity') * F('order__lineitem__price')))
似乎Sum()不能与F()表达式一起使用.还有另一种方法吗?
我试图计算一个玩家每周玩的次数如下:
player.game_objects.extra(
select={'week': 'WEEK(`games_game`.`date`)'}
).aggregate(count=Count('week'))
Run Code Online (Sandbox Code Playgroud)
但是Django抱怨说
FieldError: Cannot resolve keyword 'week' into field. Choices are: <lists model fields>
Run Code Online (Sandbox Code Playgroud)
我可以在这样的原始SQL中做到这一点
SELECT WEEK(date) as week, COUNT(WEEK(date)) as count FROM games_game
WHERE player_id = 3
GROUP BY week
Run Code Online (Sandbox Code Playgroud)
如果没有在Django中执行原始SQL,有没有一个好方法呢?
我需要得到两列的聚合值.所以首先将它们组合在一起然后得到它们sum().下面的代码自然不起作用,只是为了澄清.
它是否可能或我应该使用原始SQL?
SomeModel.objects
.filter(**something)
.aggregate(Sum('one_column' * 'another_col'))
Run Code Online (Sandbox Code Playgroud) 我有一个模型XYZ,我需要获得给定查询集的字段a,b和表达式x/y的最大值.
它适用于田野.就像是:
>>> XYZ.all().aggregate(Max('a'))
... {'a__max': 10}
Run Code Online (Sandbox Code Playgroud)
但是,我无法找到表达式的方法.尝试类似的东西:
>>> XYZ.all().aggregate(Max('x/y'))
Run Code Online (Sandbox Code Playgroud)
给出错误:
*** FieldError: Cannot resolve keyword 'x/y' into field. Choices are: a, b, x, y, id
Run Code Online (Sandbox Code Playgroud)
尝试类似的东西:
>>> XYZ.all().aggregate(Max(F('x')/F('y')))
Run Code Online (Sandbox Code Playgroud)
给出错误:
*** AttributeError: 'ExpressionNode' object has no attribute 'split'
Run Code Online (Sandbox Code Playgroud)
甚至是这样的:
XYZ.all().extra(select={'z':'x/y'}).aggregate(Max('z'))
Run Code Online (Sandbox Code Playgroud)
也不起作用,并给出与上面相同的错误:
FieldError: Cannot resolve keyword 'z' into field. Choices are: a, b, x, y, id
Run Code Online (Sandbox Code Playgroud)
我发现这样做的一个黑客是:
XYZ.all().extra(select={'z':'MAX(x/y)'})[0].z
Run Code Online (Sandbox Code Playgroud)
这实际上是有效的,因为它生成了正确的SQL,但它令人困惑,因为我确实在z atttribute获得了正确的值,但没有正确的实例,即具有该最大值的实例.
当然,我也可以使用带有extra()和order_by()的原始查询或技巧,但是我真的没理由Django以一种很好的方式支持聚合查询,但不能支持表达式甚至有自己的F表达式.
有什么办法吗?
序幕:
这是SO中经常出现的问题:
也可以在这里应用:
我已经在SO文档中编写了一个示例,但由于文档将于2017年8月8日关闭,我将遵循这个广泛上升和讨论的元答案的建议,并将我的示例转换为自我回答的帖子.
当然,我也很乐意看到任何不同的方法!
题:
假设以下型号:
class MyModel(models.Model):
number_1 = models.IntegerField()
number_2 = models.IntegerField()
date_1 = models.DateTimeField()
date_2 = models.DateTimeField()
Run Code Online (Sandbox Code Playgroud)
如何在此模型的字段之间执行算术运算?
例如,我如何找到:
number_1和number_2?date_210天或以上的物品date_1?我想编写一个 Django 查询来计算表中所有行的平均值。我的模型看起来像
class StatByDow(models.Model):
total_score = models.DecimalField(default=0, max_digits=12, decimal_places=2)
num_articles = models.IntegerField(default=0)
day_of_week = IntegerField(
null=True,
validators=[
MaxValueValidator(6),
MinValueValidator(0)
]
)
Run Code Online (Sandbox Code Playgroud)
我尝试像这样计算平均值
everything_avg = StatByDow.objects.all().aggregate(Avg(Func(F('total_score') / F('num_articles'))))
Run Code Online (Sandbox Code Playgroud)
但这会导致错误
File "/Users/davea/Documents/workspace/mainsite_project/venv/lib/python3.7/site-packages/django/db/models/query.py", line 362, in aggregate
raise TypeError("Complex aggregates require an alias")
TypeError: Complex aggregates require an alias
Run Code Online (Sandbox Code Playgroud)
计算平均值的正确方法是什么?