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.
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()
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
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.
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()
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