mirror of
https://github.com/Hopiu/django-select2.git
synced 2026-03-31 20:30:24 +00:00
Pylint and useless imports
widgets.py contains DOS and Unix line returns, I've converted it to DOS only to keep changes small in this commit.
This commit is contained in:
parent
487e55020c
commit
d24b6a5206
5 changed files with 76 additions and 58 deletions
|
|
@ -6,6 +6,7 @@ import logging
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AutoViewFieldMixin(object):
|
||||
"""
|
||||
Registers itself with AutoResponseView.
|
||||
|
|
@ -82,7 +83,6 @@ from django.forms.models import ModelChoiceIterator
|
|||
from django.db.models import Q
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.utils.encoding import smart_unicode
|
||||
from django.core.validators import EMPTY_VALUES
|
||||
|
||||
from .widgets import Select2Widget, Select2MultipleWidget,\
|
||||
HeavySelect2Widget, HeavySelect2MultipleWidget, AutoHeavySelect2Widget, \
|
||||
|
|
@ -90,6 +90,7 @@ from .widgets import Select2Widget, Select2MultipleWidget,\
|
|||
from .views import NO_ERR_RESP
|
||||
from .util import extract_some_key_val
|
||||
|
||||
|
||||
### Light general fields ###
|
||||
|
||||
class Select2ChoiceField(forms.ChoiceField):
|
||||
|
|
@ -134,7 +135,7 @@ class ModelResultJsonMixin(object):
|
|||
value. (Default is ``pk``, i.e. the id field of the model)
|
||||
:type to_field_name: :py:obj:`str`
|
||||
"""
|
||||
if self.queryset is None and not kwargs.has_key('queryset'):
|
||||
if self.queryset is None and not 'queryset' in kwargs:
|
||||
raise ValueError('queryset is required.')
|
||||
|
||||
if not self.search_fields:
|
||||
|
|
@ -201,7 +202,7 @@ class ModelResultJsonMixin(object):
|
|||
|
||||
| Assume, ``search_term == 'John'``
|
||||
| ``self.search_fields == ['first_name__icontains', 'last_name__icontains']``
|
||||
|
||||
|
||||
So, the prepared query would be::
|
||||
|
||||
{
|
||||
|
|
@ -211,7 +212,7 @@ class ModelResultJsonMixin(object):
|
|||
'and': {}
|
||||
}
|
||||
:rtype: :py:obj:`dict`
|
||||
"""
|
||||
"""
|
||||
q = None
|
||||
for field in search_fields:
|
||||
kwargs = {}
|
||||
|
|
@ -220,7 +221,7 @@ class ModelResultJsonMixin(object):
|
|||
q = Q(**kwargs)
|
||||
else:
|
||||
q = q | Q(**kwargs)
|
||||
return {'or': [q], 'and': {},}
|
||||
return {'or': [q], 'and': {}}
|
||||
|
||||
def get_results(self, request, term, page, context):
|
||||
"""
|
||||
|
|
@ -233,7 +234,7 @@ class ModelResultJsonMixin(object):
|
|||
|
||||
if self.max_results:
|
||||
min_ = (page - 1) * self.max_results
|
||||
max_ = min_ + self.max_results + 1 # fetching one extra row to check if it has more rows.
|
||||
max_ = min_ + self.max_results + 1 # fetching one extra row to check if it has more rows.
|
||||
res = list(qs.filter(*params['or'], **params['and'])[min_:max_])
|
||||
has_more = len(res) == (max_ - min_)
|
||||
if has_more:
|
||||
|
|
@ -242,7 +243,7 @@ class ModelResultJsonMixin(object):
|
|||
res = list(qs.filter(*params['or'], **params['and']))
|
||||
has_more = False
|
||||
|
||||
res = [ (getattr(obj, self.to_field_name), self.label_from_instance(obj), ) for obj in res ]
|
||||
res = [(getattr(obj, self.to_field_name), self.label_from_instance(obj), ) for obj in res]
|
||||
return (NO_ERR_RESP, has_more, res, )
|
||||
|
||||
|
||||
|
|
@ -263,7 +264,7 @@ class UnhideableQuerysetType(type):
|
|||
# class variable named - queryset, which will
|
||||
# effectively hide the queryset declared in this
|
||||
# mixin.
|
||||
dct.pop('queryset') # Throwing away the sub-class queryset
|
||||
dct.pop('queryset') # Throwing away the sub-class queryset
|
||||
dct['_subclass_queryset'] = _q
|
||||
|
||||
return type.__new__(cls, name, bases, dct)
|
||||
|
|
@ -331,10 +332,11 @@ class ModelChoiceFieldMixin(object):
|
|||
'empty_label', 'cache_choices', 'required', 'label', 'initial', 'help_text',
|
||||
])
|
||||
kargs['widget'] = kwargs.pop('widget', getattr(self, 'widget', None))
|
||||
kargs['to_field_name'] = kwargs.pop('to_field_name', 'pk')
|
||||
kargs['to_field_name'] = kwargs.pop('to_field_name', 'pk')
|
||||
|
||||
if hasattr(self, '_choices'): # If it exists then probably it is set by HeavySelect2FieldBase.
|
||||
# We are not gonna use that anyway.
|
||||
# If it exists then probably it is set by HeavySelect2FieldBase.
|
||||
# We are not gonna use that anyway.
|
||||
if hasattr(self, '_choices'):
|
||||
del self._choices
|
||||
|
||||
super(ModelChoiceFieldMixin, self).__init__(queryset, **kargs)
|
||||
|
|
@ -357,9 +359,10 @@ class ModelMultipleChoiceField(ModelChoiceFieldMixin, forms.ModelMultipleChoiceF
|
|||
queryset = property(ModelChoiceFieldMixin._get_queryset, forms.ModelMultipleChoiceField._set_queryset)
|
||||
|
||||
|
||||
### Light Fileds specialized for Models ###
|
||||
### Light Fields specialized for Models ###
|
||||
|
||||
class ModelSelect2Field(ModelChoiceField) :
|
||||
|
||||
class ModelSelect2Field(ModelChoiceField):
|
||||
"""
|
||||
Light Select2 field, specialized for Models.
|
||||
|
||||
|
|
@ -368,7 +371,7 @@ class ModelSelect2Field(ModelChoiceField) :
|
|||
widget = Select2Widget
|
||||
|
||||
|
||||
class ModelSelect2MultipleField(ModelMultipleChoiceField) :
|
||||
class ModelSelect2MultipleField(ModelMultipleChoiceField):
|
||||
"""
|
||||
Light multiple-value Select2 field, specialized for Models.
|
||||
|
||||
|
|
@ -426,7 +429,8 @@ class HeavySelect2FieldBaseMixin(object):
|
|||
if hasattr(self, 'field_id'):
|
||||
self.widget.field_id = self.field_id
|
||||
|
||||
if not choices and hasattr(self, 'choices'): # ModelChoiceField will set this to ModelChoiceIterator
|
||||
# ModelChoiceField will set this to ModelChoiceIterator
|
||||
if not choices and hasattr(self, 'choices'):
|
||||
choices = self.choices
|
||||
self.choices = choices
|
||||
|
||||
|
|
@ -494,7 +498,7 @@ class HeavyChoiceField(ChoiceMixin, forms.Field):
|
|||
try:
|
||||
value = self.coerce_value(value)
|
||||
self.validate_value(value)
|
||||
except Exception, e:
|
||||
except Exception:
|
||||
logger.exception("Exception while trying to get label for value")
|
||||
return None
|
||||
return self.get_val_txt(value)
|
||||
|
|
@ -512,6 +516,7 @@ class HeavyChoiceField(ChoiceMixin, forms.Field):
|
|||
"""
|
||||
return None
|
||||
|
||||
|
||||
class HeavyMultipleChoiceField(HeavyChoiceField):
|
||||
"""
|
||||
Reimplements :py:class:`django.forms.TypedMultipleChoiceField` in a way which suites the use of big data.
|
||||
|
|
@ -620,8 +625,9 @@ class AutoModelSelect2Field(ModelResultJsonMixin, AutoViewFieldMixin, HeavyModel
|
|||
This needs to be subclassed. The first instance of a class (sub-class) is used to serve all incoming
|
||||
json query requests for that type (class).
|
||||
"""
|
||||
__metaclass__ = UnhideableQuerysetType # Makes sure that user defined queryset class variable is replaced by
|
||||
# queryset property (as it is needed by super classes).
|
||||
# ModelChoiceField will set this to ModelChoiceIterator
|
||||
# queryset property (as it is needed by super classes).
|
||||
__metaclass__ = UnhideableQuerysetType
|
||||
|
||||
widget = AutoHeavySelect2Widget
|
||||
|
||||
|
|
@ -638,8 +644,9 @@ class AutoModelSelect2MultipleField(ModelResultJsonMixin, AutoViewFieldMixin, He
|
|||
This needs to be subclassed. The first instance of a class (sub-class) is used to serve all incoming
|
||||
json query requests for that type (class).
|
||||
"""
|
||||
__metaclass__ = UnhideableQuerysetType # Makes sure that user defined queryset class variable is replaced by
|
||||
# queryset property (as it is needed by super classes).
|
||||
# Makes sure that user defined queryset class variable is replaced by
|
||||
# queryset property (as it is needed by super classes).
|
||||
__metaclass__ = UnhideableQuerysetType
|
||||
|
||||
widget = AutoHeavySelect2MultipleWidget
|
||||
|
||||
|
|
@ -647,5 +654,3 @@ class AutoModelSelect2MultipleField(ModelResultJsonMixin, AutoViewFieldMixin, He
|
|||
self.data_view = "django_select2_central_json"
|
||||
kwargs['data_view'] = self.data_view
|
||||
super(AutoModelSelect2MultipleField, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from django import template
|
||||
from django.conf import settings
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
|
@ -7,14 +6,17 @@ from ..widgets import HeavySelect2Widget
|
|||
|
||||
__proxy_widget = HeavySelect2Widget(data_view="xyz")
|
||||
|
||||
|
||||
@register.simple_tag(name='import_django_select2_js')
|
||||
def import_js():
|
||||
return u'\n'.join(__proxy_widget.media.render_js())
|
||||
|
||||
|
||||
@register.simple_tag(name='import_django_select2_css')
|
||||
def import_css():
|
||||
return u'\n'.join(__proxy_widget.media.render_css())
|
||||
|
||||
|
||||
@register.simple_tag(name='import_django_select2_js_css')
|
||||
def import_all():
|
||||
return __proxy_widget.media.render()
|
||||
|
|
|
|||
|
|
@ -3,5 +3,5 @@ from django.conf.urls.defaults import *
|
|||
from .views import AutoResponseView
|
||||
|
||||
urlpatterns = patterns("",
|
||||
url(r"^fields/auto.json$", AutoResponseView.as_view(), name="django_select2_central_json"),
|
||||
url(r"^fields/auto.json$", AutoResponseView.as_view(), name="django_select2_central_json"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
import types
|
||||
import datetime
|
||||
import logging
|
||||
import re
|
||||
import threading
|
||||
import types
|
||||
|
||||
from django.utils.html import escape
|
||||
from django.utils.encoding import force_unicode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class JSVar(unicode):
|
||||
"""
|
||||
A JS variable.
|
||||
|
|
@ -107,7 +110,7 @@ def convert_py_to_js_data(val, id_):
|
|||
elif isinstance(val, JSFunctionInContext):
|
||||
return u"django_select2.runInContextHelper(%s, '%s')" % (val, id_)
|
||||
elif isinstance(val, JSVar):
|
||||
return val # No quotes here
|
||||
return val # No quotes here
|
||||
elif isinstance(val, dict):
|
||||
return convert_dict_to_js_map(val, id_)
|
||||
elif isinstance(val, list):
|
||||
|
|
@ -184,11 +187,6 @@ def convert_to_js_string_arr(lst):
|
|||
|
||||
### Auto view helper utils ###
|
||||
|
||||
import re
|
||||
import threading
|
||||
import datetime
|
||||
|
||||
|
||||
def synchronized(f):
|
||||
"Decorator to synchronize multiple calls to a functions."
|
||||
f.__lock__ = threading.Lock()
|
||||
|
|
@ -200,9 +198,10 @@ def synchronized(f):
|
|||
synced_f.__doc__ = f.__doc__
|
||||
return synced_f
|
||||
|
||||
|
||||
__id_store = {} # Generated Id to field instance mapping.
|
||||
__field_store = {} # Field's key to generated Id mapping.
|
||||
# Generated Id to field instance mapping.
|
||||
__id_store = {}
|
||||
# Field's key to generated Id mapping.
|
||||
__field_store = {}
|
||||
|
||||
|
||||
ID_PATTERN = r"[0-9_a-zA-Z.:+\- ]+"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ from . import __RENDER_SELECT2_STATICS as RENDER_SELECT2_STATICS
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def get_select2_js_path():
|
||||
from django.conf import settings
|
||||
if settings.configured and settings.DEBUG:
|
||||
|
|
@ -48,10 +49,10 @@ class Select2Mixin(object):
|
|||
|
||||
# For details on these options refer: http://ivaynberg.github.com/select2/#documentation
|
||||
options = {
|
||||
'minimumResultsForSearch': 6, # Only applicable for single value select.
|
||||
'placeholder': '', # Empty text label
|
||||
'allowClear': True, # Not allowed when field is multiple since there each value has a clear button.
|
||||
'multiple': False, # Not allowed when attached to <select>
|
||||
'minimumResultsForSearch': 6, # Only applicable for single value select.
|
||||
'placeholder': '', # Empty text label
|
||||
'allowClear': True, # Not allowed when field is multiple since there each value has a clear button.
|
||||
'multiple': False, # Not allowed when attached to <select>
|
||||
'closeOnSelect': False,
|
||||
}
|
||||
"""
|
||||
|
|
@ -61,7 +62,6 @@ class Select2Mixin(object):
|
|||
.. _Select2: http://ivaynberg.github.com/select2/#documentation.
|
||||
"""
|
||||
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""
|
||||
Constructor of the class.
|
||||
|
|
@ -95,7 +95,8 @@ class Select2Mixin(object):
|
|||
:type select2_options: :py:obj:`dict` or None
|
||||
|
||||
"""
|
||||
self.options = dict(self.options) # Making an instance specific copy
|
||||
# Making an instance specific copy
|
||||
self.options = dict(self.options)
|
||||
self.init_options()
|
||||
select2_options = kwargs.pop('select2_options', None)
|
||||
if select2_options:
|
||||
|
|
@ -126,7 +127,7 @@ class Select2Mixin(object):
|
|||
def set_placeholder(self, val):
|
||||
"""
|
||||
Placeholder is a value which Select2 JS library shows when nothing is selected. This should be string.
|
||||
|
||||
|
||||
:return: None
|
||||
"""
|
||||
self.options['placeholder'] = val
|
||||
|
|
@ -134,7 +135,7 @@ class Select2Mixin(object):
|
|||
def get_options(self):
|
||||
"""
|
||||
:return: Dictionary of options to be passed to Select2 JS.
|
||||
|
||||
|
||||
:rtype: :py:obj:`dict`
|
||||
"""
|
||||
options = dict(self.options)
|
||||
|
|
@ -145,7 +146,7 @@ class Select2Mixin(object):
|
|||
def render_select2_options_code(self, options, id_):
|
||||
"""
|
||||
Renders options for Select2 JS.
|
||||
|
||||
|
||||
:return: The rendered JS code.
|
||||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
|
|
@ -154,7 +155,7 @@ class Select2Mixin(object):
|
|||
def render_js_code(self, id_, *args):
|
||||
"""
|
||||
Renders the ``<script>`` block which contains the JS code for this widget.
|
||||
|
||||
|
||||
:return: The rendered JS code enclosed inside ``<script>`` block.
|
||||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
|
|
@ -165,7 +166,7 @@ class Select2Mixin(object):
|
|||
def render_inner_js_code(self, id_, *args):
|
||||
"""
|
||||
Renders all the JS code required for this widget.
|
||||
|
||||
|
||||
:return: The rendered JS code which will be later enclosed inside ``<script>`` block.
|
||||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
|
|
@ -177,14 +178,15 @@ class Select2Mixin(object):
|
|||
def render(self, name, value, attrs=None, choices=()):
|
||||
"""
|
||||
Renders this widget. Html and JS code blocks all are rendered by this.
|
||||
|
||||
|
||||
:return: The rendered markup.
|
||||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
args = [name, value, attrs]
|
||||
if choices: args.append(choices)
|
||||
if choices:
|
||||
args.append(choices)
|
||||
|
||||
s = unicode(super(Select2Mixin, self).render(*args)) # Thanks to @ouhouhsami Issue#1
|
||||
s = unicode(super(Select2Mixin, self).render(*args)) # Thanks to @ouhouhsami Issue#1
|
||||
if RENDER_SELECT2_STATICS:
|
||||
s += self.media.render()
|
||||
final_attrs = self.build_attrs(attrs)
|
||||
|
|
@ -217,7 +219,7 @@ class Select2Widget(Select2Mixin, forms.Select):
|
|||
def render_options(self, choices, selected_choices):
|
||||
if not self.is_required:
|
||||
choices = list(choices)
|
||||
choices.append(('', '', )) # Adding an empty choice
|
||||
choices.append(('', '', )) # Adding an empty choice
|
||||
return super(Select2Widget, self).render_options(choices, selected_choices)
|
||||
|
||||
|
||||
|
|
@ -253,7 +255,9 @@ class MultipleSelect2HiddenInput(forms.TextInput):
|
|||
hidden input would be removed. This way, when submitted all the selected values
|
||||
would be available as list.
|
||||
"""
|
||||
input_type = 'hidden' # We want it hidden but should be treated as if is_hidden is False
|
||||
# We want it hidden but should be treated as if is_hidden is False
|
||||
input_type = 'hidden'
|
||||
|
||||
def render(self, name, value, attrs=None, choices=()):
|
||||
attrs = self.build_attrs(attrs, multiple='multiple')
|
||||
s = unicode(super(MultipleSelect2HiddenInput, self).render(name, u"", attrs))
|
||||
|
|
@ -334,7 +338,7 @@ class HeavySelect2Mixin(Select2Mixin):
|
|||
when browser is closed.
|
||||
"""
|
||||
self.field = None
|
||||
self.options = dict(self.options) # Making an instance specific copy
|
||||
self.options = dict(self.options) # Making an instance specific copy
|
||||
self.view = kwargs.pop('data_view', None)
|
||||
self.url = kwargs.pop('data_url', None)
|
||||
self.userGetValTextFuncName = kwargs.pop('userGetValTextFuncName', u'null')
|
||||
|
|
@ -342,6 +346,7 @@ class HeavySelect2Mixin(Select2Mixin):
|
|||
|
||||
if not self.view and not self.url:
|
||||
raise ValueError('data_view or data_url is required')
|
||||
|
||||
self.options['ajax'] = {
|
||||
'dataType': 'json',
|
||||
'quietMillis': 100,
|
||||
|
|
@ -384,9 +389,12 @@ class HeavySelect2Mixin(Select2Mixin):
|
|||
|
||||
def get_options(self):
|
||||
if self.url is None:
|
||||
self.url = reverse(self.view) # We lazy resolve the view. By this time Url conf would been loaded fully.
|
||||
# We lazy resolve the view. By this time Url conf would been loaded fully.
|
||||
self.url = reverse(self.view)
|
||||
|
||||
if self.options['ajax'].get('url', None) is None:
|
||||
self.options['ajax']['url'] = self.url
|
||||
|
||||
return super(HeavySelect2Mixin, self).get_options()
|
||||
|
||||
def render_texts_for_value(self, id_, value, choices):
|
||||
|
|
@ -408,7 +416,8 @@ class HeavySelect2Mixin(Select2Mixin):
|
|||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
if value is not None:
|
||||
values = [value] # Just like forms.Select.render() it assumes that value will be single valued.
|
||||
# Just like forms.Select.render() it assumes that value will be single valued.
|
||||
values = [value]
|
||||
texts = self.render_texts(values, choices)
|
||||
if texts:
|
||||
return u"$('#%s').txt(%s);" % (id_, texts)
|
||||
|
|
@ -436,8 +445,9 @@ class HeavySelect2Widget(HeavySelect2Mixin, forms.TextInput):
|
|||
* multiple: ``False``
|
||||
|
||||
"""
|
||||
# We want it hidden but should be treated as if is_hidden is False
|
||||
input_type = 'hidden'
|
||||
|
||||
input_type = 'hidden' # We want it hidden but should be treated as if is_hidden is False
|
||||
def init_options(self):
|
||||
self.options['multiple'] = False
|
||||
|
||||
|
|
@ -464,7 +474,7 @@ class HeavySelect2MultipleWidget(HeavySelect2Mixin, MultipleSelect2HiddenInput):
|
|||
self.options.pop('minimumResultsForSearch', None)
|
||||
self.options['separator'] = JSVar('django_select2.MULTISEPARATOR')
|
||||
|
||||
def render_texts_for_value(self, id_, value, choices): # value is expected to be a list of values
|
||||
def render_texts_for_value(self, id_, value, choices):
|
||||
"""
|
||||
Renders the JS code which sets the ``txt`` attribute on the field. It gets the array
|
||||
of lables from :py:meth:`.render_texts`.
|
||||
|
|
@ -482,7 +492,8 @@ class HeavySelect2MultipleWidget(HeavySelect2Mixin, MultipleSelect2HiddenInput):
|
|||
:return: JS code which sets the ``txt`` attribute.
|
||||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
if value: # Just like forms.SelectMultiple.render() it assumes that value will be multi-valued (list).
|
||||
# Just like forms.SelectMultiple.render() it assumes that value will be multi-valued (list).
|
||||
if value:
|
||||
texts = self.render_texts(value, choices)
|
||||
if texts:
|
||||
return u"$('#%s').txt(%s);" % (id_, texts)
|
||||
|
|
@ -505,11 +516,12 @@ class AutoHeavySelect2Mixin(object):
|
|||
js += super(AutoHeavySelect2Mixin, self).render_inner_js_code(id_, *args)
|
||||
return js
|
||||
|
||||
|
||||
class AutoHeavySelect2Widget(AutoHeavySelect2Mixin, HeavySelect2Widget):
|
||||
"Auto version of :py:class:`.HeavySelect2Widget`"
|
||||
pass
|
||||
|
||||
|
||||
class AutoHeavySelect2MultipleWidget(AutoHeavySelect2Mixin, HeavySelect2MultipleWidget):
|
||||
"Auto version of :py:class:`.HeavySelect2MultipleWidget`"
|
||||
pass
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue