在django中选择DISTINCT个别列?

jam*_*ida 80 django distinct django-models django-orm django-queryset

我很好奇是否有任何方法可以在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()
Run Code Online (Sandbox Code Playgroud)

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

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

我宁愿避免使用原始SQL,但如果我必须去那里,那就没事了.虽然我以前从来没有在Django/Python中编写原始SQL.

Man*_*dan 170

从数据库中获取不同列名列表的一种方法是与... 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"
Run Code Online (Sandbox Code Playgroud)

这里有几件事需要记住.首先,这将返回一个ValuesQuerySet与a不同的行为QuerySet.当您访问say时,q(上面)的第一个元素,您将获得一个字典,而不是一个实例ProductOrder.

其次,阅读有关使用的文档中的警告说明是个好主意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()
Run Code Online (Sandbox Code Playgroud)


Wol*_*lph 47

实际上,如果你使用的是PostgreSQL,那就很简单了distinct(columns).

Productorder.objects.all().distinct('category')
Run Code Online (Sandbox Code Playgroud)

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

  • 注意:除非你使用PostgreSQL,否则你不能给distinct()一个参数.最好坚持上面接受的解决方案. (14认同)
  • -1:`distinct`不接受任何字段作为参数,文档显示并查看代码:http://code.djangoproject.com/browser/django/trunk/django/db/models/query. PY#L646 (10认同)
  • 加 1,但这里不需要 `all()` (5认同)
  • Doc:http://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct (2认同)
  • Lazerscience是正确的.`Distinct`不会接受任何列名作为参数. (2认同)
  • 现在在Django SVN中,它将在Django 1.4中 (2认同)

Mar*_*ian 17

其他的答案都很好,但这有点干净,因为它只提供了你从DISTINCT查询得到的值,而没有任何来自Django的瑕疵.

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

要么

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

而且,它没有PostgreSQL.

这比使用.distinct()效率低,假设你的数据库中的DISTINCT比python更快set,但它对于shell的noodling非常有用.


Sup*_*ova 8

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

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
Run Code Online (Sandbox Code Playgroud)