我有很多对象,其中3个有name ='AAA'
我通过'name'对它们进行分组并在组中注释num:
my_models = MyModel.objects.order_by('name').values('name').annotate(count=Count('name'))
for i in my_models:
print(i.count, i.name)
Run Code Online (Sandbox Code Playgroud)
我明白了:
3, 'AAA'
1, 'BBB'
...
Run Code Online (Sandbox Code Playgroud)
一切都很好,但是当我尝试添加一些公式来注释Count()时:
my_models = MyModel.objects.order_by('name').values('name').annotate(count=Count('name') / 2)
Run Code Online (Sandbox Code Playgroud)
我明白了:
1, 'AAA'
0, 'BBB'
...
Run Code Online (Sandbox Code Playgroud)
但预计:
1.5, 'AAA'
0.5, 'BBB'
...
Run Code Online (Sandbox Code Playgroud)
编辑:
Python部门与SQL部门通过Django的ORM不同,因此python 3中的2/1返回2.0 - OK,但不在SQL中
从Django 文档开始annotate():
使用提供的查询表达式列表注释 QuerySet 中的每个对象。表达式可以是一个简单的值、对模型(或任何相关模型)上的字段的引用,或...
是否可以为模型注释方法的结果?
我试过这样:
my_queryset.annotate(ann=my_method(request.user))
和
my_queryset.annotate(my_method(request.user))
但是我收到一个my_method未定义的错误。该方法存在并且正常工作:object.my_method(request.user)
我认为有一个装饰器可以将方法视为字段,但我似乎找不到任何相关信息(它可能用于基于 django 模板的方法调用,因此可能不相关)
这个问题提供了另一种解决方案。但我想知道是否可以对annotate结果进行处理。
假设我有以下模型结构:
Parent():
Child():
parent = ForeignKey(Parent)
GrandChild():
child = ForeignKey(Child)
state = BooleanField()
num = FloatField()
Run Code Online (Sandbox Code Playgroud)
我正在尝试从 ParentViewSet恢复以下内容:
我可以执行以下操作:
queryset = Parent.objects\
.annotate(child_count=Count('child'))\
.annotate(sum_total=Sum('child__grandchild__num'))
Run Code Online (Sandbox Code Playgroud)
这给了我 (1) 但不是 (2) 它给了我所有孙子的总和。如何在确保所有Parent对象仍在 QuerySet 中的同时适当地过滤孙子?
django django-models django-queryset django-aggregation django-annotate
我有一个有点复杂的查询,我使用带有条件表达式的注释,代码如下:
from django.db.models import Q, F, When, CharField, Value, Case
from django.contrib.auth.models import User
ATT_PREFIX = 'f'
def get_it(mymodel, fields):
q = Q(modelone__modeltwo__mymodel=mymodel)
query_set = {
'aid': F('modelone__id'),
'name': F('modelfour__name'),
}
for f in fields:
query_set[ATT_PREFIX + str(f.id)] = Case(
When(Q(modelfive__modelsix=f) &
Q(modelfive__user__email=F('email')),
then='modelfive__entry'),
default=Value(''),
output_field=CharField(),
)
return User.objects.filter(q).annotate(**query_set)
Run Code Online (Sandbox Code Playgroud)
收集的属性辅助和名称F()具有预期值。使用条件表达式的第二部分有一个问题:如果 feilds 列表包含 2 个对象,那么Case()当条件满足时我有 2 个用户对象。因此,(aid, name, f17, f18) 我得到了两个对象,而不是一个具有属性的对象:
obj1 attributes (aid, name, f17)
obj2 attributes (aid, name, f18)
Run Code Online (Sandbox Code Playgroud)
Django 1.10,Python3.5
假设我有一个对象模型A,它有一个名为created的字段,这是一个日期时间类型字段。
如果我使用注释来计算每天创建的A数,则可以使用
A.objects.annotate(date=Trunc('created', 'day', output_field=DateField()) ).values('date').order_by('date').annotate(count=Count('id'))
Run Code Online (Sandbox Code Playgroud)
之后,我可以得到结果,看起来像
[{date: '2018-07-22', count:1 }, {date: '2018-07-23', count:1 }, {date: '2018-07-25', count:1 }]
Run Code Online (Sandbox Code Playgroud)
但是,请注意,我错过了2018-07-24,因为它当天没有创建任何A. 有什么方法可以让结果包含{date: '2018-07-24', count:0 }在该查询集中吗?
我目前正在尝试根据它们出现的次数来注释和计算一些日期。
visits = Subs.objects.filter(camp=campdata, timestamp__lte=datetime.datetime.today(), timestamp__gt=datetime.datetime.today()-datetime.timedelta(days=30)).\
values('timestamp').annotate(count=Count('timestamp'))
Run Code Online (Sandbox Code Playgroud)
如果我在 for 循环中打印这个,
for a in visits:
print(a)
Run Code Online (Sandbox Code Playgroud)
我会在 Json 中取回以下内容。
{'timestamp': datetime.datetime(2018, 10, 5, 15, 16, 25, 130966, tzinfo=<UTC>), 'count': 1}
{'timestamp': datetime.datetime(2018, 10, 5, 15, 16, 45, 639464, tzinfo=<UTC>), 'count': 1}
{'timestamp': datetime.datetime(2018, 10, 6, 8, 43, 24, 721050, tzinfo=<UTC>), 'count': 1}
{'timestamp': datetime.datetime(2018, 10, 7, 4, 54, 59, tzinfo=<UTC>), 'count': 1}
Run Code Online (Sandbox Code Playgroud)
这是一个正确的方向,但是,它正在计数到第二个......我只需要几天,这样发生在 2018、10、5 的事件就会被计数:例如 2。
谁能引导我走向正确的方向?
此外,将日期转换为对 json/api 更友好的最“django”方式是什么?
我理想的 json 返回类似于
{'timestamp': 2018-10-5, 'count': 2}
Run Code Online (Sandbox Code Playgroud)
谢谢!
我遇到了一个问题,即向查询集添加注释会更改以前注释的结果。
这是(简化的)设置:
class Player(models.Model):
name = models.CharField()
class Unit(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE,
related_name='unit_set')
rarity = models.IntegerField()
class Gear(models.Model):
pass
class UnitGear(models.Model):
unit = models.ForeignKey(Unit, on_delete=models.CASCADE,
related_name='ug_set')
gear = models.ForeignKey(Gear, on_delete=models.PROTECT)
Run Code Online (Sandbox Code Playgroud)
用稀有度 7 单位的数量来注释玩家效果很好:
Player.objects.annotate(
rarity7_count=Count(unit_set__rarity=7)
).values_list('name', 'rarity7_count')
[('Player1', 170),
('Player2', 172),
('Player3', 164),
...,
)]
Run Code Online (Sandbox Code Playgroud)
上面返回的值rarity7_count是正确的。
如果我添加以下附加注释,情况就不再是这样:
Player.objects.annotate(
rarity7_count=Count(unit_set__rarity=7),
gear_count=Count(unit_set__ug_set)
).values_list('name', 'rarity7_count', 'gear_count')
[('Player1', 476, 456),
('Player2', 490, 466),
('Player3', 422, 433),
...,
)]
Run Code Online (Sandbox Code Playgroud)
请注意值是如何rarity7_count变化的——这些值不再正确!gear_count然而,的值是正确的。
这是为什么?如何让两个注释同时工作而不互相干扰?我已经尝试过各种各样的事情,但目前不知道如何做到这一点。
我有一些模型,正在尝试加快列出用户的页面的速度。
问题是我正在利用模型方法来显示一些数据 - 但是当我列出用户时,它会多次访问数据库,最终UserUser导致数百个额外查询(当列表中有数千个对象时,会出现数千个查询) )所以这对性能造成了严重影响。
从那时起我就开始使用annotateand ,prefetch_related这大大减少了查询。我只是有点不知道如何注释。
我有一个模型方法(在Summation模型上),用于获取Evaluation用户的数据摘要,如下所示:
def evaluations_summary(self):
evaluations_summary = (
self.evaluation_set.all()
.values("evaluation_type__name")
.annotate(Count("evaluation_type"))
)
return evaluations_summary
Run Code Online (Sandbox Code Playgroud)
我试图弄清楚如何注释对象上的特定查询User。
因此,这种关系看起来User有多个Summations,但只有一个是“活动的”,这就是我们在列表中显示的那个User。每个Summation都有多个Evaluations- 我们也试图展示其摘要。
这里是代码相关部分的摘要(包括Summation模型方法,它给出了当前正在“工作”以根据需要显示数据的示例) - 我还制作了一个Pastebin 示例以便于查看。
# MODELS
class User(AbstractUser):
employee_no = models.IntegerField(default=1)
...all the other usual attributes...
class Summation(CreateUpdateMixin, CreateUpdateUserMixin):
# CreateUpdateMixin adds 'created_at' & 'updated_at
# CreateUpdateUserMixin adds 'created_by' & …Run Code Online (Sandbox Code Playgroud) python django django-models django-rest-framework django-annotate
我有一个公司和用户模型以及相关模型 CompanyRecruiter:
class CompanyRecruiter(models.Model):
organization = models.ForeignKey(Company, related_name="company_recruiters")
recruiter = models.ForeignKey(User, related_name="company_recruiters")
Run Code Online (Sandbox Code Playgroud)
我想注释作为招聘人员的用户的用户 ID 列表,以便公司稍后能够对其进行过滤:
Company.objects.annotate(some_stuff=some_other_stuff).values_list("user_ids", flat=True)
# [ [1, 2], [1, 56], [] ]
Run Code Online (Sandbox Code Playgroud)
我已经尝试使用自定义聚合和子查询但没有成功。我用的是postgres。
我像这样注释一个查询集:
class ItemQuerySet(models.QuerySet):
def annotate_subitem_stats(self):
return self.annotate(
count_subitems=Count('subitems'),
has_sent_subitems=Case(
When(subitems__status=Status.sent, then=Value(True)),
default=Value(False)
),
)
Run Code Online (Sandbox Code Playgroud)
在此示例中,SubItem是一个具有 外键的模型Item。
当我运行这段代码时,发生了奇怪的行为。假设我们有 1Item和 2SubItem链接到它。一个子项目的状态已发送,而另一子项目则没有。当我在查询集上运行注释时,查询集返回该项目两次,一个has_sent_subitems设置为True,另一个设置为False。另一件奇怪的事情是,一个重复项具有count_subitems == 1,另一个重复项具有count_subitems == 1,就好像查询集已将项目拆分为两行,一行为 where status == 'sent',另一行为 where status != 'sent'。
带注释的查询集基本上如下所示:
[
{
'name': 'Item Name',
'count_subitems': 1,
'has_sent_subitem': False
},
{
'name': 'Item Name',
'count_subitems': 1,
'has_sent_subitem': True
}
]
Run Code Online (Sandbox Code Playgroud)
这就是数据库的样子,使用伪代码:
item = Item()
SubItem(item=item, status=draft)
SubItem(item=item, status=sent) …Run Code Online (Sandbox Code Playgroud)