Seleccionar DISTINTAS columnas individuales en django?


Tengo curiosidad si hay alguna manera de hacer una consulta en Django que no sea un "SELECT * FROM..." debajo. Estoy tratando de hacer un "SELECT DISTINCT columnName FROM ... " en su lugar.

Específicamente tengo un modelo que se parece a:

class ProductOrder(models.Model):
   Product  = models.CharField(max_length=20, promary_key=True)
   Category = models.CharField(max_length=30)
   Rank = models.IntegerField()

Donde el Rank es un rango dentro de un Category. Me gustaría poder iterar sobre todas las Categorías haciendo alguna operación en cada rango dentro de esa categoría.

Me gustaría primero obtener una lista de todas las categorías en el sistema y luego consultar todos los productos en esa categoría y repetir hasta que se procese cada categoría.

Prefiero evitar SQL crudo, pero si tengo que ir allí, eso estaría bien. Aunque nunca he codificado SQL raw en Django / Python antes.

Author: DhiaTN, 2010-10-04

4 answers

Una forma de obtener la lista de nombres de columna distintos de la base de datos es usar distinct() en conjunto con values().

En su caso puede hacer lo siguiente para obtener los nombres de distintas categorías:

q = ProductOrder.objects.values('Category').distinct()
print q.query # See for yourself.

# The query would look something like
# SELECT DISTINCT "app_productorder"."category" FROM "app_productorder"

Hay un par de cosas para recordar aquí. Primero, esto devolverá un ValuesQuerySet que se comporta de manera diferente a un QuerySet. Cuando accedes a decir, el primer elemento de q (arriba) obtendrás un diccionario, NO es una instancia de ProductOrder.

En segundo lugar, sería una buena idea leer la nota de advertencia en los documentos sobre el uso de distinct(). El ejemplo anterior funcionará, pero todas las combinaciones de distinct() y values() pueden no hacerlo.

PS: es una buena idea utilizar nombres en minúsculas para campos en un modelo. En su caso, esto significaría reescribir su modelo como se muestra a continuación:

class ProductOrder(models.Model):
    product  = models.CharField(max_length=20, primary_key=True)
    category = models.CharField(max_length=30)
    rank = models.IntegerField()
 134
Author: Manoj Govindan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-09 10:06:12

En realidad es bastante simple si está usando PostgreSQL, simplemente use distinct(columns).

Productorder.objects.all().distinct('category')

Tenga en cuenta que esta característica se ha incluido en Django desde 1.4

 34
Author: Wolph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-12 18:53:25

Las otras respuestas están bien, pero esto es un poco más limpio, ya que solo da los valores como se obtendría de una consulta DISTINTA, sin ningún cruft de Django.

>>> set(ProductOrder.objects.values_list('category', flat=True))
{u'category1', u'category2', u'category3', u'category4'}

O

>>> list(set(ProductOrder.objects.values_list('category', flat=True)))
[u'category1', u'category2', u'category3', u'category4']

Y, funciona sin PostgreSQL.

Esto es menos eficiente que usar a .distinct (), suponiendo que DISTINCT en tu base de datos es más rápido que python set, pero es genial para noodear alrededor del shell.

 12
Author: Mark Chackerian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-02 23:16:55

Orden del usuario por con ese campo, y luego hacer distinto.

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
 6
Author: Vikram S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-15 08:31:43