Выберите ОТЛИЧИТЬ отдельные столбцы в Django? - PullRequest
77 голосов
/ 04 октября 2010

Мне любопытно, есть ли способ сделать запрос в 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, но если бы мне пришлось идти туда, это было бы хорошо.Хотя я никогда раньше не кодировал сырой SQL в Django / Python.

Ответы [ 4 ]

160 голосов
/ 04 октября 2010

Один из способов получить список отдельных имен столбцов из базы данных - использовать 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().Приведенный выше пример будет работать, но все комбинации 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()
43 голосов
/ 04 октября 2010

На самом деле довольно просто, если вы используете PostgreSQL , просто используйте distinct(columns).

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

Обратите внимание, что эта функция была включена в Django начиная с 1.4

15 голосов
/ 03 февраля 2015

Остальные ответы хороши, но это немного чище, поскольку дает только те значения, которые вы получили бы из запроса 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, но это здороводля лапши вокруг раковины.

7 голосов
/ 15 октября 2015

Порядок пользователя с этим полем, а затем сделать разные.

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