在django中选择DISTINCT各个列?


93

我很好奇,是否有任何方法可以在Django中进行查询,而该查询不在SELECT * FROM...下面。我正在尝试执行“ SELECT DISTINCT columnName FROM ...”。

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

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

其中Rank是内的排名Category。我希望能够遍历所有类别,对该类别中的每个等级进行一些操作。

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

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

Answers:


185

从数据库获取不同列名称列表的一种方法是与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

其次,最好阅读文档中有关using 的警告说明distinct()。上面的例子可以工作,但所有的组合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实例,这是很好的方法;-)
Jonathan Liuti 2012年

61

实际上,如果您使用的是PostgreSQL非常简单,只需使用distinct(columns)documentation)。

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

请注意,此功能自1.4起已包含在Django中


@ lazerscience,@ Manoj Govindan:对不起,你是对的。看来我已经修补了Django以添加该功能。我已经添加了补丁链接
Wolph

3
这是目前在Django SVN并会在Django 1.4
威尔哈迪

14
注意:除非您使用的是PostgreSQL,否则不能给distinct()一个参数。最好坚持上述公认的解决方案。
Mark Chackerian

在测试中,这can_distinct_on_fields似乎仅适用于Postgres
Skylar Saveland 2013年

3
加1,但all()在此没有必要
安东尼Hatchkins

17

其他答案很好,但是这样做更干净一点,因为它只提供了从DISTINCT查询中获得的值,而没有Django的麻烦。

>>> 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的情况下也可以工作。

假定使用数据库中的DISTINCT比使用python更快,这要比使用.distinct()效率低set。但这对于在shell周围闲逛非常有用。


values_list不会放入DISTINCTsql查询,因此如果有的话,它将带来多个值。
mehmet

13

用户通过该字段排序,然后进行区分。

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.