sim*_*rsh 304 python django django-models
我查询一个模型,
Members.objects.all()
Run Code Online (Sandbox Code Playgroud)
它返回说
Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop
Run Code Online (Sandbox Code Playgroud)
我想要的是,知道最好的Django方法来触发group_by查询到我的数据库,就像,
Members.objects.all().group_by('designation')
Run Code Online (Sandbox Code Playgroud)
哪个当然不起作用.我知道我们可以在"django/db/models/query.py"上做一些技巧,但我很想知道如何在没有修补的情况下做到这一点.
Guð*_*r H 446
from django.db.models import Count
Members.objects.values('designation').annotate(dcount=Count('designation'))
Run Code Online (Sandbox Code Playgroud)
这导致类似的查询
SELECT designation, COUNT(designation) AS dcount
FROM members GROUP BY designation
Run Code Online (Sandbox Code Playgroud)
输出将是形式
[{'designation': 'Salesman', 'dcount': 2},
{'designation': 'Manager', 'dcount': 2}]
Run Code Online (Sandbox Code Playgroud)
Mic*_*ael 49
一个简单的解决方案,但不是正确的方法是使用RAW-SQL:
http://docs.djangoproject.com/en/dev/topics/db/sql/#topics-db-sql
另一种解决方案是使用group_by属性:
results = Members.objects.raw('SELECT * FROM myapp_members GROUP BY designation')
Run Code Online (Sandbox Code Playgroud)
您现在可以迭代结果变量以检索结果.请注意,group_by没有记录,可能会在将来的Django版本中更改.
而且......你为什么要使用group_by?如果您不使用聚合,则可以使用order_by来获得相似的结果.
ino*_*tia 21
您还可以使用regroup模板标记按属性进行分组.来自文档:
cities = [
{'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
{'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
{'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
{'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
{'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]
...
{% regroup cities by country as country_list %}
<ul>
{% for country in country_list %}
<li>{{ country.grouper }}
<ul>
{% for city in country.list %}
<li>{{ city.name }}: {{ city.population }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)
看起来像这样:
它也适用于QuerySet我相信的.
来源:https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#regroup
小智 9
您也可以直接使用内置的 python itertools.groupby:
from itertools import groupby
designation_key_func = lambda member: member.designation
queryset = Members.objects.all().select_related("designation")
for designation, member_group in groupby(queryset, designation_key_func):
print(f"{designation} : {list(member_group)}")
Run Code Online (Sandbox Code Playgroud)
不需要原始 sql、子查询、第三方库或模板标签,在我看来是 Pythonic 和明确的。
Django 不支持 free group by queries。我以非常糟糕的方式学到了它。ORM 的设计目的不是在不使用自定义 SQL 的情况下支持您想做的事情。您仅限于:
cr.execute 句子(以及对结果的手工解析)。.annotate() (按句子分组在 .annotate() 的子模型中执行,例如聚合 lines_count=Count('lines')))。在一个QuerySet qs,你可以调用qs.query.group_by = ['field1', 'field2', ...],但它是有风险的,如果你不知道查询你编辑的内容,并没有保证能正常工作,而不是打破QuerySet对象的内部。此外,它是一个内部(未记录的)API,您不应该直接访问它,以免代码与未来的 Django 版本不再兼容。
该文档说您可以使用值对 queryset 进行分组。
class Travel(models.Model):
interest = models.ForeignKey(Interest)
user = models.ForeignKey(User)
time = models.DateTimeField(auto_now_add=True)
# Find the travel and group by the interest:
>>> Travel.objects.values('interest').annotate(Count('user'))
<QuerySet [{'interest': 5, 'user__count': 2}, {'interest': 6, 'user__count': 1}]>
# the interest(id=5) had been visited for 2 times,
# and the interest(id=6) had only been visited for 1 time.
>>> Travel.objects.values('interest').annotate(Count('user', distinct=True))
<QuerySet [{'interest': 5, 'user__count': 1}, {'interest': 6, 'user__count': 1}]>
# the interest(id=5) had been visited by only one person (but this person had
# visited the interest for 2 times
Run Code Online (Sandbox Code Playgroud)
您可以使用以下代码找到所有书籍并按名称对它们进行分组:
Book.objects.values('name').annotate(Count('id')).order_by() # ensure you add the order_by()
Run Code Online (Sandbox Code Playgroud)
您可以在这里观看一些备忘单。
以下模块允许您对 Django 模型进行分组,并且仍然可以在结果中使用 QuerySet:https : //github.com/kako-nawao/django-group-by
例如:
from django_group_by import GroupByMixin
class BookQuerySet(QuerySet, GroupByMixin):
pass
class Book(Model):
title = TextField(...)
author = ForeignKey(User, ...)
shop = ForeignKey(Shop, ...)
price = DecimalField(...)
Run Code Online (Sandbox Code Playgroud)
class GroupedBookListView(PaginationMixin, ListView):
template_name = 'book/books.html'
model = Book
paginate_by = 100
def get_queryset(self):
return Book.objects.group_by('title', 'author').annotate(
shop_count=Count('shop'), price_avg=Avg('price')).order_by(
'name', 'author').distinct()
def get_context_data(self, **kwargs):
return super().get_context_data(total_count=self.get_queryset().count(), **kwargs)
Run Code Online (Sandbox Code Playgroud)
'书/books.html'
<ul>
{% for book in object_list %}
<li>
<h2>{{ book.title }}</td>
<p>{{ book.author.last_name }}, {{ book.author.first_name }}</p>
<p>{{ book.shop_count }}</p>
<p>{{ book.price_avg }}</p>
</li>
{% endfor %}
</ul>
Run Code Online (Sandbox Code Playgroud)
与annotate/ aggregatebasic Django 查询的不同之处在于使用相关字段的属性,例如book.author.last_name.
如果需要已分组的实例的PK,请添加以下注释:
.annotate(pks=ArrayAgg('id'))
Run Code Online (Sandbox Code Playgroud)
注意:ArrayAgg是 Postgres 特定的函数,从 Django 1.9 开始可用:https : //docs.djangoproject.com/en/1.10/ref/contrib/postgres/aggregates/#arrayagg
| 归档时间: |
|
| 查看次数: |
264398 次 |
| 最近记录: |