Source code for tags_input.widgets

from django.conf import settings
from django import forms
from django.template.loader import render_to_string
from django import urls
from django.contrib.admin import widgets

try:  # pragma: no cover
    from collections import OrderedDict
except ImportError:  # pragma: no cover
    from django.utils.datastructures import SortedDict as OrderedDict


[docs]class TagsInputWidgetBase(forms.SelectMultiple): def __init__(self, on_add_tag=None, on_remove_tag=None, on_change_tag=None, *args, **kwargs): self.on_add_tag = on_add_tag self.on_remove_tag = on_remove_tag self.on_change_tag = on_change_tag forms.SelectMultiple.__init__(self, *args, **kwargs)
[docs] def build_attrs(self, base_attrs, extra_attrs=None, **kwargs): '''Compatibility function for the behavior changes in Django 1.11+''' attrs = dict(base_attrs or {}, **kwargs) if extra_attrs: # pragma: no cover attrs.update(extra_attrs) return attrs
[docs] def render(self, name, value, attrs=None, choices=(), renderer=None): context = self.build_attrs(attrs, name=name) context['on_add_tag'] = self.on_add_tag context['on_remove_tag'] = self.on_remove_tag context['on_change_tag'] = self.on_change_tag context['STATIC_URL'] = settings.STATIC_URL context['mapping'] = self.mapping context['autocomplete_url'] = urls.reverse( 'tags_input:autocomplete', kwargs=dict( app=self.mapping['app'], model=self.mapping['model'], fields='-'.join(self.mapping['fields']), ), ) if value: fields = self.mapping['fields'] join_func = self.mapping['join_func'] ids = [] for v in value: if isinstance(v, int): ids.append(v) values_map = OrderedDict(map( join_func, self.mapping['queryset'] .filter(pk__in=ids) .values('pk', *fields) .order_by('pk') )) values = [] for v in value: if isinstance(v, int): values.append(values_map[v]) else: values.append(v) context['values'] = ', '.join(values) return render_to_string('tags_input_widget.html', context)
[docs] def value_from_datadict(self, data, files, name): tags = data.get(name, '').split(',') incomplete = data.get(name + '_incomplete', '') if incomplete != data.get(name + '_default'): tags += incomplete.split(',') return [t.strip() for t in tags if t]
[docs]class TagsInputWidget(TagsInputWidgetBase):
[docs] class Media: css = { 'all': ( 'jquery.tagsinput-revisited-2.0.min.css', ), } js = ( 'jquery.tagsinput-revisited-2.0.min.js', ) enable_jquery = getattr(settings, 'TAGS_INPUT_INCLUDE_JQUERY', True) if enable_jquery: # pragma: no cover css['all'] += 'jquery-ui-1.12.1.min.css', js = ( 'jquery-3.2.1.min.js', 'jquery-ui-1.12.1.min.js', ) + js
[docs]class AdminTagsInputWidget( widgets.FilteredSelectMultiple, TagsInputWidgetBase): # This class inherits FilteredSelectMultiple because the Django admin # handles the FilteredSelectMultiple differently from regular widgets @property def media(self): return forms.Media(js=self.Media.js, css=self.Media.css)
[docs] class Media: css = getattr(settings, 'TAGS_INPUT_ADMIN_CSS', { 'all': ( 'jquery.tagsinput-revisited-2.0.min.css', 'jquery-ui-1.12.1.min.css', ), }) js = getattr(settings, 'TAGS_INPUT_ADMIN_JS', ( 'jquery-3.2.1.min.js', 'jquery-ui-1.12.1.min.js', 'jquery.tagsinput-revisited-2.0.min.js', ))