Eu consulto um modelo:
Members.objects.all()
E retorna:
Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop
O que eu quero é conhecer a melhor maneira do Django de disparar uma group_by
consulta ao meu banco de dados, como:
Members.objects.all().group_by('designation')
O que não funciona, é claro. Eu sei que podemos fazer alguns truques django/db/models/query.py
, mas estou curioso para saber como fazê-lo sem aplicar patches.
python
django
django-models
simplyharsh
fonte
fonte
Members.objects.filter(date=some_date).values('designation').annotate(dcount=Count('designation'))
Members.objects.order_by('disignation').values('designation').annotate(dcount=Count('designation'))
Uma solução fácil, mas não a maneira correta, é usar o SQL bruto :
Outra solução é usar a
group_by
propriedade:Agora você pode iterar sobre a variável results para recuperar seus resultados. Note que
group_by
não está documentado e pode ser alterado na versão futura do Django.E ... por que você quer usar
group_by
? Se você não usar agregação, poderá usarorder_by
para obter um resultado semelhante.fonte
Você também pode usar a
regroup
tag de modelo para agrupar por atributos. Dos documentos:Se parece com isso:
Também funciona em
QuerySet
s eu acredito.fonte: https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#regroup
editar: observe que a
regroup
tag não funciona como seria de esperar se sua lista de dicionários não for classificada por chave. Funciona iterativamente. Portanto, classifique sua lista (ou conjunto de consultas) pela chave da garoupa antes de passá-la para aregroup
tag.fonte
Você precisa fazer o SQL customizado, conforme exemplificado neste trecho:
SQL personalizado via subconsulta
Ou em um gerenciador personalizado, como mostrado nos documentos on-line do Django:
Adicionando métodos extras do Manager
fonte
O Django não suporta grupo livre por consultas . Eu aprendi isso da pior maneira possível. O ORM não foi projetado para oferecer suporte a coisas como o que você deseja fazer, sem usar o SQL personalizado. Você está limitado a:
cr.execute
sentenças (e uma análise feita à mão do resultado)..annotate()
(o grupo por sentenças é realizado no modelo filho para .annotate (), em exemplos como agregando lines_count = Count ('lines'))).Em um conjunto de consultas,
qs
você pode chamar,qs.query.group_by = ['field1', 'field2', ...]
mas é arriscado se você não souber qual consulta está editando e não tem garantia de que funcionará e não interromperá as internas do objeto QuerySet. Além disso, é uma API interna (não documentada) que você não deve acessar diretamente sem arriscar que o código não seja mais compatível com futuras versões do Django.fonte
Há um módulo que permite agrupar modelos do Django e ainda trabalhar com um QuerySet no resultado: https://github.com/kako-nawao/django-group-by
Por exemplo:
'book / books.html'
A diferença para as consultas
annotate
/aggregate
Django básicas é o uso dos atributos de um campo relacionado, por exemplobook.author.last_name
.Se você precisar das PKs das instâncias que foram agrupadas, adicione a seguinte anotação:
NOTA:
ArrayAgg
é uma função específica do Postgres, disponível a partir do Django 1.9: https://docs.djangoproject.com/en/1.10/ref/contrib/postgres/aggregates/#arrayaggfonte
values
método. É para um propósito diferente, eu acho.values
é um SQLselect
enquantogroup_by
é um SQLgroup by
(como o nome indica ...). Por que o voto negativo? Estamos usando esse código em produção para implementargroup_by
instruções complexas .group_by
"se comporta principalmente como o método values, mas com uma diferença ..." O documento não menciona SQLGROUP BY
e o caso de uso que ele fornece não sugere que isso tenha algo a ver com SQLGROUP BY
. Retiro a votação quando alguém deixar isso claro, mas esse documento é realmente enganoso.values
, descobri que perdi quevalues
funciona como um GROUP BY. É minha culpa. Eu acho que é mais simples de usar doitertools.groupby
que esse django-group-by quandovalues
é insuficiente.group by
de cima com uma simplesvalues
chamada - com ou semannotate
e sem buscar tudo no banco de dados. Sua sugestão deitertools.groupby
trabalhos para conjuntos de dados pequenos, mas não para vários milhares de conjuntos de dados que você provavelmente deseja paginar. Obviamente, nesse ponto, você terá que pensar em um índice de pesquisa especial que contenha dados preparados (já agrupados), de qualquer maneira.O documento diz que você pode usar valores para agrupar o conjunto de consultas.
Você pode encontrar todos os livros e agrupá-los por nome usando este código:
Você pode assistir a algumas folhas aqui .
fonte
Se não me engano, você pode usar o que quer que seja o conjunto de consultas .group_by = [' field ']
fonte
primeiro você precisa importar Sum então ..
fonte