在django中选择DISTINCT个别列?

时间:2010-10-04 00:14:20

标签: django django-models distinct django-queryset django-orm

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

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

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

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

4 个答案:

答案 0 :(得分:156)

从数据库中获取不同列名列表的一种方法是将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不同。当您访问say 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 :(得分:39)

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

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

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

答案 2 :(得分:14)

其他答案都很好,但这样更清晰,因为它只提供了从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()效率低,假设你的数据库中的DISTINCT比python set更快,但它很适合在shell周围进行noodling。

答案 3 :(得分:7)

使用该字段的用户订单,然后执行不同的操作。

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