2013-08-14 3 views
6

Я хотел бы добавить или цепочку нескольких Querysets в Django, сохраняя порядок каждого из них (а не результат). Я использую стороннюю библиотеку для разбивки на результат, и он принимает только списки или запросы. Я пробовал эти параметры:Как связать запросы Django, сохраняя индивидуальный заказ

Queryset join: Не сохраняет порядок в отдельных запросах, поэтому я не могу использовать это.

result = queryset_1 | queryset_2 

Использование itertools: Вызов list() на объекте цепи фактически оценивает querysets, и это может вызвать много накладных расходов. Не так ли?

result = list(itertools.chain(queryset_1, queryset_2)) 

Как вы думаете, куда мне идти?

ответ

4

Если querysets бывают разных моделей, вы должны оценить их в списки, а затем вы можете просто добавить:

result = list(queryset_1) + list(queryset_2) 

Если они такие же модели, вы должны объединить запросы с помощью Q object и ' order_by ("queryset_1 field", "queryset_2 field") '.

Правильный ответ во многом зависит от того, почему вы хотите объединить их и как вы собираетесь использовать результаты.

+0

Я делаю сложные Seach на одной и той же модели расщепленного в нескольких запросах. Каждый из них извлекает записи, соответствующие определенному условию, и каждый из них упорядочивается определенным образом. Результат должен включать результаты каждого запроса и должен поддерживать порядок каждого из этих наборов запросов. Поэтому я не могу использовать здесь объекты 'Q', так как мне не разрешено делать несколько' order_by() 'в том же запросе. Я хотел бы избежать вызова 'list()' на каждом наборе запросов, чтобы избежать доступа к базе данных, получая слишком много объектов в памяти. – Caumons

+0

Считаете ли вы возможным составить чистый SQL-запрос, который вернет единый набор строк, упорядоченных и отфильтрованных точно так, как вы хотите? Если нет, то один QuerySet тоже не сможет этого сделать.Например, если вы заказываете два набора результатов несовместимыми способами. Если вы работаете над этой несовместимостью, используя сложное соединение из двух четко упорядоченных наборов результатов, это не то, что может сделать ORJ DJANO. – Demiurge

+0

Я не хочу вдаваться в чистый SQL столько, сколько я могу остаться с ORM Django. Я просто просил это посмотреть, есть ли лучшая альтернатива тому, что я делаю (в настоящее время использую второй пример) с ограниченным запросом, чтобы не иметь тысячи объектов в памяти. – Caumons

0

Если вам нужно слить два запроса в третий запрос, вот пример, используя _result_cache.

модель

class ImportMinAttend(models.Model): 
    country=models.CharField(max_length=2, blank=False, null=False) 
    status=models.CharField(max_length=5, blank=True, null=True, default=None) 

Из этой модели, я хочу, чтобы отобразить список всех строк, что:

  1. (запрос 1) пустой статус идти первым, упорядоченные по странам
  2. (запрос 2) непустое состояние в секунду, упорядочено по странам

Я хочу объединить запрос 1 и запрос 2.

#get all the objects 
    queryset=ImportMinAttend.objects.all() 

    #get the first queryset 
    queryset_1=queryset.filter(status=None).order_by("country") 
    #len or anything that hits the database 
    len(queryset_1) 

    #get the second queryset 
    queryset_2=queryset.exclude(status=None).order_by("country") 

    #append the second queryset to the first one AND PRESERVE ORDER 
    for query in queryset_2: 
     queryset_1._result_cache.append(query) 

    #final result 
    queryset=queryset_1 

Это может быть очень эффективным, но это работает :).

+0

Это кажется намного более эффективным, чем вызов list() на обоих запросах. Если вы перебираете наименьшее, это кажется лучше. Что мне не нравится, это изменение частного атрибута _result_cache ... Вы уверены, что это безопасно? – Caumons

+0

Этот подход по-прежнему будет оценивать все запросы, которые совпадают с созданием списка из них, чего не хочет автор вопроса. –

Смежные вопросы