Source code for dal_alight_queryset_sequence.views

"""Views for autocomplete-light widget and QuerySetSequence-based business logic."""

from collections import OrderedDict
from functools import reduce

from django import http
from django.db.models import Q
from django.utils.html import format_html
from queryset_sequence import QuerySetSequence

from dal_queryset_sequence.views import BaseQuerySetSequenceView


[docs] class AlightQuerySetSequenceView(BaseQuerySetSequenceView): """ Combines QuerySetSequence support with autocomplete-light HTML fragments. Returns results grouped by model type, rendered as HTML divs instead of JSON. Group headers use ``class="autocomplete-light-group"``; individual results carry a ``data-value`` attribute with the ``ctype_pk-object_pk`` composite identifier used by ``dal_queryset_sequence``. Example usage:: path( 'your-generic-autocomplete/', autocomplete.AlightQuerySetSequenceView.as_view( queryset=autocomplete.QuerySetSequence( Group.objects.all(), TestModel.objects.all(), ) ), name='your-generic-autocomplete', ) Compatible with :py:mod:`~dal_alight_queryset_sequence.widgets` and the fields of :py:mod:`~dal_contenttypes.fields` for generic-relation autocompletes. """
[docs] def render_to_response(self, context): """Return an HTML fragment grouped by model type.""" groups = OrderedDict() for result in context['object_list']: groups.setdefault(type(result), []).append(result) html = [] for model, results in groups.items(): verbose_name = model._meta.verbose_name html.append(format_html( '<div class="autocomplete-light-group">{}</div>', verbose_name, )) for result in results: html.append(format_html( '<div data-value="{}">{}</div>', self.get_result_value(result), str(result), )) return http.HttpResponse( ''.join(html), content_type='text/html; charset=utf-8', )
[docs] class AlightQuerySetSequenceAutoView(AlightQuerySetSequenceView): """ AlightQuerySetSequenceAutoView class. Filters the queryset based on the models and filter attributes defined on an :py:class:`AlightGenericForeignKeyModelField <dal_alight_queryset_sequence.fields.AlightGenericForeignKeyModelField>`. ``self.model_choice`` is generated from that field; see its docstring for the expected structure. """
[docs] def get_queryset(self): """Return queryset filtered according to self.model_choice.""" queryset_models = [] for model_args in self.model_choice: model = model_args[0] filter_value = model_args[1] kwargs_model = { '{}__icontains'.format(filter_value): self.q if self.q else '' } forward_filtered = [Q(**kwargs_model)] for forward in model_args[2] if len(model_args) > 2 else []: field_value = self.forwarded.get(forward[0]) if field_value is None: continue field_key = '{}__icontains'.format(forward[1]) forward_filtered.append(Q(**{field_key: field_value})) # Combine filters with AND. and_forward_filtered = reduce(lambda x, y: x & y, forward_filtered) queryset_models.append(model.objects.filter(and_forward_filtered)) # Aggregate querysets and limit each to an equal share of the page. qs = QuerySetSequence(*queryset_models) qs = self.mixup_querysets(qs) return qs