Выберите DISTINCT отдельных столбцов в django?
Мне любопытно, есть ли способ сделать запрос в 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
- ранг внутри a Category
. Я хотел бы иметь возможность перебирать все категории, выполняющие некоторую операцию над каждым рангом в этой категории.
Я бы хотел сначала получить список всех категорий в системе, а затем запросить все продукты этой категории и повторить до тех пор, пока не будет обработана каждая категория.
Я бы предпочел избежать сырого SQL, но если мне нужно туда идти, все будет хорошо. Хотя я никогда раньше не кодировал необработанный SQL в Django/Python.
Ответы
Ответ 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"
Здесь можно вспомнить пару вещей. Во-первых, это вернет a ValuesQuerySet
, который ведет себя иначе, чем a QuerySet
. Когда вы скажете, первый элемент 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()
Ответ 2
Это довольно просто на самом деле , если вы используете PostgreSQL, просто используйте distinct(columns)
.
Productorder.objects.all().distinct('category')
Обратите внимание, что эта функция включена в Django с версии 1.4
Ответ 3
Другие ответы в порядке, но это немного чище, потому что он дает только такие значения, которые вы могли бы получить из запроса 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
, но он отлично подходит для noodling вокруг оболочки.
Ответ 4
Пользователь упорядочивается с этим полем, а затем выполняет различные операции.
ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()