web-dev-qa-db-ja.com

djangoのDISTINCT個別の列を選択しますか?

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をコーディングしたことはありませんが。

80
jamida

データベースから個別の列名のリストを取得する1つの方法は、- 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のインスタンスではなく、dictionaryが返されます。

第二に、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()
_
166
Manoj Govindan

実際には非常に簡単ですPostgreSQLを使用している場合distinct(columns)を使用してください。

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

この機能はDjango= 1.4以降に含まれていることに注意してください。

44
Wolph

他の答えは問題ありませんが、これはDjangoからの残骸なしでDISTINCTクエリから取得するような値のみを提供するという点で、少し簡潔です。

>>> 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 setよりも速いと仮定します。

15
Mark Chackerian

ユーザーはそのフィールドで並べ替えてから、個別に行います。

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