Source code for autocomplete_light.channel.generic
from django.contrib.contenttypes.models import ContentType
from autocomplete_light.generic import GenericForeignKeyField
from .base import ChannelBase
__all__ = ['GenericChannelBase']
[docs]class GenericChannelBase(ChannelBase):
"""
Wraps around multiple querysets, from multiple model classes, rather than
just one.
This is also interresting as it overrides **all** the default model logic
from ChannelBase. Hell, you could even copy it and make your
CSVChannelBase, a channel that uses a CSV file as backend. But only if
you're really bored or for a milion dollars.
"""
[docs] def result_as_value(self, result):
"""
Rely on GenericForeignKeyField to return a string containing the
content type id and object id of the result.
Because this channel is made for that field, and to avoid code
duplication.
"""
field = GenericForeignKeyField()
return field.prepare_value(result)
[docs] def order_results(self, results):
"""
Return results, **without** doing any ordering.
In most cases, you would not have to override this method as querysets
should be ordered by default, based on model.Meta.ordering.
"""
return results # can't order because don't know what model type
[docs] def get_results(self, values=None):
"""
Return results for each queryset returned by get_querysets().
Note that it limits each queryset's to self.limit_result. If you want a
maximum of 12 suggestions and have a total of 4 querysets, then
self.limit_results should be set to 3.
"""
for model, queryset in self.get_querysets().items():
if values is not None:
queryset = self.values_filter(queryset, values)
elif self.request:
queryset = self.query_filter(queryset)
for result in self.order_results(queryset)[0:self.limit_results]:
yield result
[docs] def are_valid(self, values):
"""
Return True if it can find all the models refered by values.
"""
for value in values:
# some nice Q action could be done here
content_type_id, object_id = value.split('-')
model = ContentType.objects.get_for_id(
content_type_id).model_class()
if not model.objects.filter(pk=object_id).count():
return False
return True
[docs] def values_filter(self, results, values):
"""
Filter out any result from results that is not refered to by values.
"""
ctype = ContentType.objects.get_for_model(results.model).pk
ids = [x.split('-')[1] for x in values
if int(x.split('-')[0]) == ctype]
return results.filter(pk__in=ids)