2010-10-04 67 views
58

我很好奇,如果有什么办法可以在Django中进行查询,那么下面不是“SELECT * FROM...”。我试图做一个“SELECT DISTINCT columnName FROM ...”而不是。在django中选择DISTINCT个别列?

具体来说,我有一个模型,看起来像:

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

其中RankCategory内的排名。我希望能够遍历所有类别在该类别中的每个等级上进行一些操作。

我想先获得系统中所有类别的列表,然后查询该类别中的所有产品并重复,直到处理完每个类别。

我宁愿避免原始SQL,但如果我必须去那里,那很好。虽然我以前从未在Django/Python中编写过原始SQL。

回答

122

一种方法来从数据库中获取不同的列名的名单中包括在Django是结合使用distinct()values()

在你的情况,你可以做以下来获得不同类别的名称:

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" 

有几件事情要记住。首先,这将返回一个ValuesQuerySet,其行为与QuerySet的行为不同。当你访问说,q(上面)的第一个元素,你会得到一个字典,而不是ProductOrder的实例。

其次,在关于使用distinct()的文档中阅读warning note将是一个好主意。上面的例子可以工作,但是distinct()values()的所有组合都不可以。

PS:它是用小写名称模型中的领域是一个好主意。在你的情况,这将意味着重写你的模型如下图所示:

class ProductOrder(models.Model): 
    product = models.CharField(max_length=20, primary_key=True) 
    category = models.CharField(max_length=30) 
    rank = models.IntegerField() 
+1

下面介绍的方法现在在django 1.4中可用,并且如果您需要具有字段感知明确性的ProductOrder实例,那么该方法很不错;-) – 2012-10-16 15:03:18

25

这实际上很简单如果您使用PostgreSQL,只需使用distinct(columns)

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

注意,这个功能已经从1.4

+2

文件:http://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct – kafuchau 2010-10-04 00:24:23

+8

-1:'distinct'不采取任何领域的说法,该文件显示,并查看代码:http://code.djangoproject.com/browser/django/trunk/django/db/models/query.py#L646 – 2010-10-04 01:27:49

+2

Lazerscience是正确的。 'Distinct'不接受任何列名作为参数。 – 2010-10-04 05:17:28

10

其他的答案都很好,但是这是一个少许清洁剂,因为它不仅赋予了价值,就像您从一个DISTINCT查询得到,而不从Django的任何cruft。

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

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

而且,它的工作原理没有PostgreSQL的。

这比使用a的效率低。distinct(),假设数据库中的DISTINCT比python set更快,但对于在shell中进行操作非常有用。

+0

'values_list'不在SQL查询中放置'DISTINCT',所以如果有的话会带来多个值。 – mehmet 2016-06-29 22:10:36

+1

不,它不 - 这就是'集'是为 – 2016-06-29 23:11:28

+0

我没看到:) – mehmet 2016-06-30 01:00:07

7

用户通过该字段排序,然后执行截然不同的操作。

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()