import re from django.core.urlresolvers import reverse from django.core.serializers.json import DjangoJSONEncoder from django.http import HttpResponse from django.utils.encoding import smart_unicode, force_unicode try: import json except ImportError: from django.utils import simplejson as json class LookupBase(object): @classmethod def name(cls): app_name = cls.__module__.split('.')[-2].lower() class_name = cls.__name__.lower() name = u'%s-%s' % (app_name, class_name) return name @classmethod def url(cls): return reverse('autocomplete-lookup', args=[cls.name()]) def get_query(self, request, term): return [] def get_item_label(self, item): return smart_unicode(item) def get_item_id(self, item): return smart_unicode(item) def get_item_value(self, item): return smart_unicode(item) def get_item(self, value): return value def create_item(self, value): raise NotImplemented() def format_item(self, item): return { 'id': self.get_item_id(item), 'value': self.get_item_value(item), 'label': self.get_item_label(item) } def results(self, request): term = request.GET.get('term', '') raw_data = self.get_query(request, term) data = [] for item in raw_data: data.append(self.format_item(item)) content = json.dumps(data, cls=DjangoJSONEncoder, ensure_ascii=False) return HttpResponse(content, content_type='application/json') class LookupAlreadyRegistered(Exception): pass class LookupNotRegistered(Exception): pass class LookupInvalid(Exception): pass class LookupRegistry(object): def __init__(self): self._registry = {} def validate(self, lookup): if not issubclass(lookup, LookupBase): raise LookupInvalid(u'Registered lookups must inherit from the \ LookupBase class') def register(self, lookup): self.validate(lookup) name = force_unicode(lookup.name()) if name in self._registry: raise LookupAlreadyRegistered(u'The name %s is already registered'\ % name) self._registry[name] = lookup def unregister(self, lookup): self.validate(lookup) name = force_unicode(lookup.name()) if name not in self._registry: raise LookupNotRegistered(u'The name %s is not registered' % name) del self._registry[name] def get(self, key): return self._registry.get(key, None) class ModelLookup(LookupBase): model = None filters = {} search_field = '' def get_query(self, request, term): qs = self.get_queryset() if term and self.search_field: qs = qs.filter(**{self.search_field: term}) return qs def get_queryset(self): qs = self.model._default_manager.get_query_set() if self.filters: qs = qs.filter(**self.filters) return qs def get_item_id(self, item): return item.pk def get_item(self, value): item = None if value: try: item = self.get_queryset().filter(pk=value)[0] except IndexError: pass return item def create_item(self, value): data = {} if self.search_field: field_name = re.sub(r'__\w+$', '', self.search_field) if field_name: data = {field_name: value} return self.model(**data)