Code


Version 2 (modified by marinho, 6 years ago) (diff)

--

Para trabalhar com GROUP BY no Django, há duas formas.

Usando método extra da QuerySet

usar o método "extra" da queryset para adicionar um campo extra à sua seleção, e este recebe o valor de uma totalização/agregação com o mesmo fim de um GROUP BY.

Exemplo:

class CharacterManager(models.Manager):
    def get_query_set(self):
        qs = super(CharacterManager, self).get_query_set()
        return qs.extra(
                select={
                    'kills': 'select count(*) from wars_characterdeathkiller k where wars_character.id = k.killer_id',
                    'deaths': 'select count(*) from wars_characterdeath d where wars_character.id = d.character_id',
                    },
                )

class Character(models.Model):
    name = models.CharField(max_length=50)

    objects = CharacterManager()

Usando a conexão direta com o banco

Você irá usar a conexão direta com o banco (django.db.connection) para fazer o select com GROUP BY sem que seja parte de uma seleção de outro registro.

Exemplo:

from itertools import *
from django.db import connection

def query_to_dicts(query_string, *query_args):
    """Run a simple query and produce a generator
    that returns the results as a bunch of dictionaries
    with keys for the column values selected.
    http://blog.doughellmann.com/2007/12/using-raw-sql-in-django.html
    """
    cursor = connection.cursor()
    cursor.execute(query_string, query_args)
    col_names = [desc[0] for desc in cursor.description]
    while True:
        row = cursor.fetchone()
        if row is None:
            break
        row_dict = dict(izip(col_names, row))
        yield row_dict
    return

def mais_vistos_dia(self, data, limite=100):
    sql = """
    SELECT
     VU.video_id as video_id,
     count(VU.id) as quantidade_visitas
    FROM videos_historico VU
    WHERE date(VU.data_lancamento) = %s
    GROUP BY VU.video_id
    ORDER BY quantidade_visitas DESC
    LIMIT %s
    """

    return query_to_dicts(sql, data.isoformat(), limite)

No código descrito acima, o resultado do método mais_vistos_dia retorna um dicionário com os valores retornados.

Para facilitar o trabalho, o código utiliza uma função encontrada em http://blog.doughellmann.com/2007/12/using-raw-sql-in-django.html para transformar os dados retornados do banco de dados em dicionário.


Tire outras dúvidas em nosso CookBook em Português