Преимущество общих конструкторов

Можно использовать 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 работает.

9
задан notnoop 19 August 2009 в 02:44
поделиться

1 ответ

Единственное использование, которое я могу придумать, было бы, если бы конструктору нужно было использовать универсальный объект во время его работы, но не сохранять этот объект после его завершения.

Например, :

<T> NonGeneric(T[] blank, List<T> list) {
    // Sort that list
    T[] array = list.toArray(blank);
    Arrays.sort(array);

    // Pull out the values as strings
    this.list = new ArrayList<String>(array.length);
    for (T value : array) {
        this.list.add(value.toString());
    }
}

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

5
ответ дан 3 November 2019 в 07:14
поделиться
Другие вопросы по тегам:

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