Подтвердить что ты не робот

Выберите 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.

4b9b3361

Ответ 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()