Получение отдельных строк на основе определенного поля из базы данных в Django

Мне нужно построить запрос в Django, и мне интересно, возможно ли это как-то (это может быть действительно очевидно, но я его упускаю...).

У меня есть обычный запрос Model.objects.filter(x=True)[:5], который может возвращать такие результаты:

FirstName    LastName    Country
Bob           Jones        UK
Bill          Thompson     UK
David         Smith        USA

Мне нужно только захватить строки, которые отличаются на основе поля Country, что-то вроде Model.objects.filter(x=True).distinct('Country')[:5] было бы идеальным, но это невозможно с Django.

Строки, которые я хочу, чтобы запрос захватил в конечном итоге:

FirstName    LastName    Country
Bob           Jones        UK
David         Smith        USA

Мне также нужно, чтобы запрос использовал тот же порядок, который установлен в мета-классе модели (т.е. я никоим образом не могу переопределить порядок).

Как мне это сделать?

Большое спасибо.


person Dx143    schedule 23.11.2009    source источник
comment
Мне нужны только пять верхних строк из БД.   -  person Dx143    schedule 23.11.2009
comment
Это сложный вопрос, но я не уверен, что полностью понимаю вопрос. Вам нужны пять верхних строк, в которых страна отличается?   -  person jathanism    schedule 23.11.2009
comment
@S.Lott, нарезка набора запросов не превращает его в список. Dx143 прав, что это способ просто получить 5 лучших элементов из базы данных.   -  person Daniel Roseman    schedule 23.11.2009
comment
Похоже, для этого есть билет: code.djangoproject.com/ticket/6422   -  person shacker    schedule 04.02.2010


Ответы (3)


Я не проверял это, но мне кажется, что дикт должен выполнять эту работу, хотя тогда порядок может быть отключен:

d = {}
for x in Model.objects.all():
    d[x.country] = x

records_with_distinct_countries = d.values()
person extraneon    schedule 23.11.2009
comment
То же самое можно выполнить с захватом значений в файле set. - person jathanism; 23.11.2009
comment
Не совсем. Страны можно поместить в набор, так как они неизменяемы. Но модели точно не неизменяемые, поэтому не могут быть в наборе. Вот почему я использую dict, неизменяемую страну в качестве ключа и запись в качестве значения. Мне довелось использовать ключи dict как набор (что концептуально так и есть) без потери записи. - person extraneon; 24.11.2009

Я думаю, что @skrobul находится на правильном пути, но немного не в том направлении.

Я не думаю, что вы сможете сделать это с помощью одного запроса, потому что метод distinct() добавляет к запросу модификатор SELECT DISTINCT, который действует на всю строку. Скорее всего, вам придется создать список стран, а затем вернуть ограниченные наборы запросов на основе повторения этого списка.

Что-то вроде этого:

maxrows = 5
countries = set([x.country for x in Model.objects.all()])
rows = []
count = 0
for c in countries:
    if count >= maxrows:
        break

    try:
        rows.append(Model.objects.filter(country=c)[0])
    except Model.DoesNotExist:
        pass

    count += 1

Это очень общий пример, но он дает ожидаемый результат.

person jathanism    schedule 23.11.2009

Можете ли вы опубликовать необработанный SQL, который возвращает то, что вы хотите, из исходной базы данных? У меня есть подозрение, что реальная проблема здесь - это структура запроса/данных...

person morrissimo    schedule 23.11.2009