Как объединить 2 или более наборов запросов в представлении Django?

Да, там происходит присваивание, как и в цикле for. Никакая новая область не создается.

Это определенно ожидаемое поведение: в каждом цикле значение привязано к указанному вами имени. Например,

>>> x=0
>>> a=[1,54,4,2,32,234,5234,]
>>> [x for x in a if x>32]
[54, 234, 5234]
>>> x
5234

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

601
задан Bill Armstrong 16 June 2018 в 13:45
поделиться

5 ответов

Конкатенация querysets в список является самым простым подходом. Если база данных будет поражена для всего querysets так или иначе (например, потому что результат должен быть отсортирован), это не добавит далее стоимость.

from itertools import chain
result_list = list(chain(page_list, article_list, post_list))

Используя itertools.chain быстрее, чем цикличное выполнение каждый список и элементы добавления один за другим, так как itertools реализован в C. Это также использует меньше памяти, чем преобразование каждого queryset в список перед конкатенацией.

Теперь возможно отсортировать получающийся список, например, по дате (согласно просьбе в комментарии hasen j к другому ответу). Эти sorted() функция удобно принимает генератор и возвращает список:

result_list = sorted(
    chain(page_list, article_list, post_list),
    key=lambda instance: instance.date_created)

при использовании Python 2.4 или позже можно использовать attrgetter вместо лямбды. Я не забываю читать об этом являющийся быстрее, но я не видел значимой разности оборотов для миллиона списков объекта.

from operator import attrgetter
result_list = sorted(
    chain(page_list, article_list, post_list),
    key=attrgetter('date_created'))
990
ответ дан akaihola 16 June 2018 в 13:45
поделиться
  • 1
    Сеанс, что это может , делает при определенных условиях, what' s названный " interposer" или " человек в middle" нападение. Это позволяет ему играть клиент к серверу, серверу клиенту, и прервать все. Существуют меры защиты от этого. Google " человек в middle" и SSL для деталей. – Charlie Martin 26 February 2009 в 16:27

Большая оборотная сторона Вашего текущего подхода является своей неэффективностью с большими наборами результата поиска, поскольку у Вас есть к выпадающему весь набор результатов от базы данных каждый раз, даже при том, что Вы только намереваетесь отобразить одну страницу результатов.

, Чтобы к только выпадающему объекты Вам на самом деле нужно от базы данных, необходимо использовать разбиение на страницы на QuerySet, не список. Если Вы делаете это, Django на самом деле нарезает QuerySet, прежде чем запрос будет выполнен, таким образом, SQL-запрос будет использовать СМЕЩЕНИЕ и ОГРАНИЧИВАТЬ, чтобы только получить записи, Вы на самом деле отобразитесь. Но Вы не можете сделать этого, если Вы не можете переполнить свой поиск в единый запрос так или иначе.

, Учитывая, что все три из Ваших моделей имеют заголовок и поля тела, почему бы не использовать образцовое наследование ? Просто имейте все три модели, наследовались от общего предка, который имеет заголовок и тело, и выполните поиск как единый запрос на модели предка.

27
ответ дан Carl Meyer 16 June 2018 в 13:45
поделиться
  • 1
    gcc делает то же самое (я уже видел несколько раз, что он использовал lea и компиляцию Вашего примера программы, который это использовало, добавляют и с-m32 и с-m64). – CesarB 24 October 2008 в 23:39

вот идея... просто выпадающая одна полная страница результатов каждого из трех, и затем выведите 20 наименее полезных..., это устраняет большой querysets и тот способ, которым Вы только жертвуете небольшой производительностью вместо много

6
ответ дан Jiaaro 16 June 2018 в 13:45
поделиться
  • 1
    это? Первый I' m слышащий об этом. На самом деле я обычно слышу это it' s один из лучших компиляторов уровня ПК для оптимизации. – James Curran 24 October 2008 в 20:46

Можно использовать QuerySetChain класс ниже. При использовании его с paginator Django он должен только поразить базу данных COUNT(*) запросы для всего querysets и SELECT() запросы только для тех querysets, записи которых отображены на текущей странице.

Примечание, которое необходимо указать template_name= при использовании QuerySetChain с универсальными представлениями, даже если цепочечный querysets все использование та же модель.

from itertools import islice, chain

class QuerySetChain(object):
    """
    Chains multiple subquerysets (possibly of different models) and behaves as
    one queryset.  Supports minimal methods needed for use with
    django.core.paginator.
    """

    def __init__(self, *subquerysets):
        self.querysets = subquerysets

    def count(self):
        """
        Performs a .count() for all subquerysets and returns the number of
        records as an integer.
        """
        return sum(qs.count() for qs in self.querysets)

    def _clone(self):
        "Returns a clone of this queryset chain"
        return self.__class__(*self.querysets)

    def _all(self):
        "Iterates records in all subquerysets"
        return chain(*self.querysets)

    def __getitem__(self, ndx):
        """
        Retrieves an item or slice from the chained set of results from all
        subquerysets.
        """
        if type(ndx) is slice:
            return list(islice(self._all(), ndx.start, ndx.stop, ndx.step or 1))
        else:
            return islice(self._all(), ndx, ndx+1).next()

В Вашем примере, использование было бы:

pages = Page.objects.filter(Q(title__icontains=cleaned_search_term) |
                            Q(body__icontains=cleaned_search_term))
articles = Article.objects.filter(Q(title__icontains=cleaned_search_term) |
                                  Q(body__icontains=cleaned_search_term) |
                                  Q(tags__icontains=cleaned_search_term))
posts = Post.objects.filter(Q(title__icontains=cleaned_search_term) |
                            Q(body__icontains=cleaned_search_term) | 
                            Q(tags__icontains=cleaned_search_term))
matches = QuerySetChain(pages, articles, posts)

Затем использование matches с paginator как Вы использовало result_list в Вашем примере.

itertools модуль был представлен в Python 2.3, таким образом, это должно быть доступно во всех версиях Python, Django работает.

75
ответ дан akaihola 16 June 2018 в 23:45
поделиться
  • 1
    математически вычисленный против общедоступной части CA, чтобы проверить, что половой орган CA на самом деле вошел в систему сертификат и себя. – X-Istence 26 February 2009 в 19:28

Попробуйте это:

matches = pages | articles | posts

Он сохраняет все функции наборов запросов, что хорошо, если вы хотите order_by или аналогичный.

Обратите внимание: это не работает для наборов запросов из двух разных моделей.

435
ответ дан 22 November 2019 в 21:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: