Виділити ВИЗНАЧЕННЯ окремих стовпців у django?


93

Мені цікаво, чи є якийсь спосіб зробити запит у 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()

де the Rank- ранг у межах Category. Я хотів би мати можливість переглядати всі категорії, виконуючи певні операції щодо кожного рангу в цій категорії.

Я хотів би спочатку отримати список усіх категорій у системі, а потім здійснити запит щодо всіх продуктів цієї категорії та повторювати, поки не буде оброблена кожна категорія.

Я волів би уникати необробленого SQL, але якщо мені доведеться туди піти, це було б добре. Хоча я ніколи раніше не кодував необроблений SQL в Django / Python.

Відповіді:


185

Одним із способів отримати список різних імен стовпців з бази даних є використання 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. Коли ви отримуєте доступ до 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()

1
Описаний нижче спосіб тепер доступний у django 1.4 і приємно, якщо вам потрібен екземпляр ProductOrder із чітко вираженим полем ;-)
Джонатан Люті,

61

Насправді це дуже просто, якщо ви використовуєте PostgreSQL , просто використовуйте distinct(columns)( документацію ).

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

Зверніть увагу, що ця функція була включена в Django з 1.4


@lazerscience, @Manoj Govindan: Вибач, ти маєш рацію. Здається, я виправив Django, щоб додати цю функцію. Я додав посилання на патч
Wolph

3
Зараз це в Django SVN, а буде в Django 1.4
Will Hardy

14
Примітка: якщо ви не використовуєте PostgreSQL, ви не можете наводити аргумент distinct (). Найкраще дотримуватися прийнятого вище рішення.
Mark Chackerian

в тестах це, can_distinct_on_fieldsздається, лише для Postgres
Skylar Saveland

3
плюс 1, але all()тут не потрібно
Ентоні Хетчкінс

17

Інші відповіді чудові, але це трохи чіткіше, оскільки воно надає лише ті значення, які ви отримали б із запиту 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 у вашій базі даних швидший, ніж пітон set, але він чудово підходить для локшини навколо оболонки.


values_listне поміщає DISTINCTв запит sql, тому це призведе до кількох значень, якщо такі будуть.
Мехмет

13

Користувач упорядковується за допомогою цього поля, а потім робить чітко.

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.