我很好奇是否有任何方法可以在 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。
从数据库中获取不同列名列表的一种方法是将 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"
这里有几件事要记住。首先,这将返回一个行为不同于 QuerySet
的 ValuesQuerySet
。当您访问 q
的第一个元素(上图)时,您将获得 dictionary,而不是 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()
实际上很简单如果您使用的是 PostgreSQL,只需使用 distinct(columns)
(documentation)。
Productorder.objects.all().distinct('category')
请注意,此功能自 1.4 以来已包含在 Django 中
can_distinct_on_fields
,它似乎是 Postgres-only
all()
用户使用该字段排序,然后进行区分。
ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
其他答案很好,但这更简洁一些,因为它只给出了从 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 周围闲逛。
更新:这个答案非常适合在开发期间在 Django shell 中进行查询。不要在生产中使用此解决方案,除非您绝对确定在应用 set
之前您将始终获得少量结果。否则,从性能的角度来看,这是一个糟糕的主意。
values_list
不会将 DISTINCT
放在 sql 查询中,因此如果有的话,这会带来多个值。
where
语句。像select distinct(app_productorder.category) from app_productorder where app_productorder.rank <30;
?select distinct on
的好提示:geekytidbits.com/postgres-distinct-on