我正在尝试按name每个记录的字段字符对记录进行分组,并限制每个组中的项目,这是我想出的:
desired_letters = ['a','b','c',..,'z']
some_variable = {}
for desired_letter in desired_letters:
some_variable += User.objects.all().order_by("name").filter(name__startswith=desired_letter)[:10]
Run Code Online (Sandbox Code Playgroud)
我在for循环中运行此查询并更改desired_letter为我想要的字母,有没有其他方法来优化此解决方案并使其成为单个查询而不是for循环?
AKS*_*AKS 13
从其他答案中的评论:
我实际上是在寻找一种在django orm中实现Group By First Character的方法
我会按照以下3个步骤来做到这一点:
使用name字段的第一个字母注释每个记录.为此你可以使用Substr功能Lower
from django.db.models.functions import Substr, Lower
qs = User.objects.annotate(fl_name=Lower(Substr('name', 1, 1)))
Run Code Online (Sandbox Code Playgroud)接下来,使用此第一个字母对所有记录进行分组,并获取ID的计数.这可以通过使用值注释来完成:
# since, we annotated each record we can use the first letter for grouping, and
# then get the count of ids for each group
from django.db.models import Count
qs = qs.values('fl_name').annotate(cnt_users=Count('id'))
Run Code Online (Sandbox Code Playgroud)接下来,您可以使用第一个字母订购此查询集:
qs = qs.order_by('fl_name')
Run Code Online (Sandbox Code Playgroud)将所有这些结合在一个声明中:
from django.db.models.functions import Substr, Lower
from django.db.models import Count
qs = User.objects \
.annotate(fl_name=Lower(Substr('name', 1, 1))) \
.values('fl_name') \
.annotate(cnt_users=Count('id')) \
.order_by('fl_name')
Run Code Online (Sandbox Code Playgroud)
最后,您的查询集看起来像这样.请注意,我在注释时将第一个字符转换为小写字母.如果您不需要,可以删除该Lower功能:
[{'fl_name': 'a', 'cnt_users': 12},
{'fl_name': 'b', 'cnt_users': 4},
...
...
{'fl_name': 'z', 'cnt_users': 3},]
Run Code Online (Sandbox Code Playgroud)
如果,你需要一个字母和计数字典:
fl_count = dict(qs.values('fl_name', 'cnt_users'))
# {'a': 12, 'b': 4, ........., 'z': 3}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1926 次 |
| 最近记录: |