Source code for easy_select2.widgets

import json

from django import forms
from django.conf import settings
from django.utils.safestring import mark_safe


[docs]class Select2Mixin(object): """ This mixin provides a mechanism to construct custom widget class, that will be rendered using Select2 input. Generally should be mixed with widgets that render select input. """ html = """<div class="field-easy-select2" style="display:none" id="{id}" {options}></div>""" def __init__(self, select2attrs=None, *args, **kwargs): """ Initialize default select2 attributes. If width is not provided, sets Select2 width to 250px. Args: select2attrs: a dictionary, which then passed to Select2 constructor function as options. """ self.select2attrs = select2attrs or {} assert_msg = "select2attrs attribute must be dict, not {}" assert isinstance(self.select2attrs, dict), assert_msg.format( self.select2attrs.__class__.__name__ ) if 'width' not in self.select2attrs: self.select2attrs.update({'width': '250px'}) self.static_settings() super(Select2Mixin, self).__init__(*args, **kwargs) def static_settings(self): SELECT2_USE_BUNDLED_SELECT2 = getattr( settings, 'SELECT2_USE_BUNDLED_SELECT2', True) if SELECT2_USE_BUNDLED_SELECT2: SELECT2_VERSION = '4.0.13' DEFAULT_SELECT2_CSS = 'easy_select2/vendor/select2-{}/css/select2.min.css'.format(SELECT2_VERSION) DEFAULT_SELECT2_JS = 'easy_select2/vendor/select2-{}/js/select2.min.js'.format(SELECT2_VERSION) else: # use Django admin's copy DEFAULT_SELECT2_CSS = 'admin/css/vendor/select2/select2.min.css' DEFAULT_SELECT2_JS = 'admin/js/vendor/select2/select2.full.min.js' SELECT2_JS = getattr( settings, 'SELECT2_JS', DEFAULT_SELECT2_JS, ) SELECT2_CSS = getattr( settings, 'SELECT2_CSS', DEFAULT_SELECT2_CSS, ) SELECT2_USE_BUNDLED_JQUERY = getattr( settings, 'SELECT2_USE_BUNDLED_JQUERY', True) self.SELECT2_WIDGET_JS = [ 'easy_select2/js/init.js', 'easy_select2/js/easy_select2.js', SELECT2_JS, ] if SELECT2_USE_BUNDLED_JQUERY: jquery_min_file = 'easy_select2/vendor/jquery/jquery-3.5.1.min.js' self.SELECT2_WIDGET_JS.insert(0, jquery_min_file) else: self.SELECT2_WIDGET_JS.insert(0, 'admin/js/jquery.init.js') self.SELECT2_WIDGET_CSS = { 'screen': [ SELECT2_CSS, 'easy_select2/css/easy_select2.css', ], } # This function is taken from django-select2
[docs] def get_options(self): """Return dictionary of options to be used by Select2.""" return self.select2attrs
# This function is taken from django-select2
[docs] def render_select2_options_code(self, options, id_): """Render options for select2.""" output = [] for key, value in options.items(): if isinstance(value, (dict, list)): value = json.dumps(value) output.append("data-{name}='{value}'".format( name=key, value=mark_safe(value))) return mark_safe(' '.join(output))
[docs] def render_js_code(self, id_, *args, **kwargs): """Render html container for Select2 widget with options.""" if id_: options = self.render_select2_options_code( dict(self.get_options()), id_) return mark_safe(self.html.format(id=id_, options=options)) return u''
[docs] def render(self, name, value, attrs=None, **kwargs): """ Extend base class's `render` method by appending javascript inline text to html output. """ output = super(Select2Mixin, self).render( name, value, attrs=attrs, **kwargs) id_ = attrs['id'] output += self.render_js_code( id_, name, value, attrs=attrs, **kwargs) return mark_safe(output)
@property def media(self): return forms.Media( css=self.SELECT2_WIDGET_CSS, js=self.SELECT2_WIDGET_JS )
[docs]class Select2(Select2Mixin, forms.Select): """Implement single-valued select widget with Select2.""" pass
[docs]class Select2Multiple(Select2Mixin, forms.SelectMultiple): """Implement multiple select widget with Select2.""" pass