views:

77

answers:

2

I'm curious if there's any way to do a query in Django that's not a "SELECT * FROM..." underneath. I'm trying to do a "SELECT DISTINCT columnName FROM ..." instead.

Specifically I have a model that looks like:

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

where the Rank is a rank within a Category. I'd like to be able to iterate over all the Categories doing some operation on each rank within that category.

I'd like to first get a list of all the categories in the system and then query for all products in that category and repeat until every category is processed.

I'd rather avoid raw SQL, but if I have to go there, that'd be fine. Though I've never coded raw SQL in Django/Python before.

+1  A: 

It's quite simple actually, just use distinct(columns).

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

You have to patch Django with one of the following patches to make it work: http://code.djangoproject.com/ticket/6422

WoLpH
Doc: http://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct
kchau
-1: `distinct` doesn't take any fields as argument, the documentation shows that and also check out the code: http://code.djangoproject.com/browser/django/trunk/django/db/models/query.py#L646
lazerscience
@WoLpH: Lazerscience is correct. `Distinct` will not accept any column names as arguments.
Manoj Govindan
@lazerscience, @Manoj Govindan: I'm sorry, you're right. It seems that I have patched Django to add that feature. I've added a link to the patch
WoLpH
thanks for all the extra info!
jamida
+2  A: 

One way to get the list of distinct column names from the database is to use distinct() in conjunction with values().

In your case you can do the following to get the names of distinct categories:

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"

There are a couple of things to remember here. First, this will return a ValuesQuerySet which behaves differently from a QuerySet. When you access say, the first element of q (above) you'll get a dictionary, NOT an instance of ProductOrder.

Second, it would be a good idea to read the warning note in the docs about using distinct(). The above example will work but all combinations of distinct() and values() may not.

PS: it is a good idea to use lower case names for fields in a model. In your case this would mean rewriting your model as shown below:

class ProductOrder(models.Model):
    product  = models.CharField(max_length=20, promary_key=True)
    category = models.CharField(max_length=30)
    rank = models.IntegerField()
Manoj Govindan