mirror of
https://github.com/Hopiu/django-select2.git
synced 2026-05-02 02:44:42 +00:00
Code cleanup -- Added pep8 tests for package.
This commit is contained in:
parent
18fa453ac0
commit
2cfbfd3325
14 changed files with 199 additions and 157 deletions
|
|
@ -33,7 +33,6 @@ matrix:
|
|||
- python: "3.2"
|
||||
- python: "3.3"
|
||||
- python: "3.4"
|
||||
- python: "pypy"
|
||||
- python: "pypy3"
|
||||
install:
|
||||
- pip install --upgrade pip
|
||||
|
|
@ -43,6 +42,7 @@ install:
|
|||
- pip install coveralls
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
script:
|
||||
coverage run --source=django_select2 runtests.py
|
||||
- isort -c -vb -rc ./django_select2
|
||||
- coverage run --source=django_select2 runtests.py
|
||||
after_success:
|
||||
coveralls
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
This is a Django_ integration of Select2_.
|
||||
|
||||
|
|
@ -75,6 +76,7 @@ The view - `Select2View`, exposed here is meant to be used with 'Heavy' fields a
|
|||
.. _Read more: http://blog.applegrew.com/2012/08/django-select2/
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -108,13 +110,22 @@ try:
|
|||
logger.warn("You need not turn on ENABLE_SELECT2_MULTI_PROCESS_SUPPORT when GENERATE_RANDOM_SELECT2_ID is disabled.")
|
||||
__ENABLE_MULTI_PROCESS_SUPPORT = False
|
||||
|
||||
from .widgets import Select2Widget, Select2MultipleWidget, HeavySelect2Widget, HeavySelect2MultipleWidget, \
|
||||
AutoHeavySelect2Widget, AutoHeavySelect2MultipleWidget, HeavySelect2TagWidget, AutoHeavySelect2TagWidget
|
||||
from .fields import Select2ChoiceField, Select2MultipleChoiceField, HeavySelect2ChoiceField, \
|
||||
HeavySelect2MultipleChoiceField, HeavyModelSelect2ChoiceField, HeavyModelSelect2MultipleChoiceField, \
|
||||
ModelSelect2Field, ModelSelect2MultipleField, AutoSelect2Field, AutoSelect2MultipleField, \
|
||||
AutoModelSelect2Field, AutoModelSelect2MultipleField, HeavySelect2TagField, AutoSelect2TagField, \
|
||||
from .widgets import (
|
||||
Select2Widget, Select2MultipleWidget,
|
||||
HeavySelect2Widget, HeavySelect2MultipleWidget,
|
||||
AutoHeavySelect2Widget, AutoHeavySelect2MultipleWidget,
|
||||
HeavySelect2TagWidget, AutoHeavySelect2TagWidget
|
||||
) # NOQA
|
||||
from .fields import (
|
||||
Select2ChoiceField, Select2MultipleChoiceField,
|
||||
HeavySelect2ChoiceField, HeavySelect2MultipleChoiceField,
|
||||
HeavyModelSelect2ChoiceField, HeavyModelSelect2MultipleChoiceField,
|
||||
ModelSelect2Field, ModelSelect2MultipleField,
|
||||
AutoSelect2Field, AutoSelect2MultipleField,
|
||||
AutoModelSelect2Field, AutoModelSelect2MultipleField,
|
||||
HeavySelect2TagField, AutoSelect2TagField,
|
||||
HeavyModelSelect2TagField, AutoModelSelect2TagField
|
||||
) # NOQA
|
||||
from .views import Select2View, NO_ERR_RESP
|
||||
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
|
|
@ -122,4 +133,3 @@ try:
|
|||
except ImportError:
|
||||
if logger.isEnabledFor(logging.INFO):
|
||||
logger.info("Django not found.")
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
from models import KeyMap
|
||||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from .models import KeyMap
|
||||
|
||||
|
||||
class Client(object):
|
||||
|
||||
def set(self, key, value):
|
||||
"""
|
||||
This method is used to set a new value
|
||||
|
|
@ -11,10 +14,10 @@ class Client(object):
|
|||
if o is None:
|
||||
o = KeyMap()
|
||||
o.key = key
|
||||
|
||||
|
||||
o.value = value
|
||||
o.save()
|
||||
|
||||
|
||||
def get(self, key):
|
||||
"""
|
||||
This method is used to retrieve a value
|
||||
|
|
|
|||
|
|
@ -1,9 +1,29 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Contains all the Django fields for Select2.
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import copy
|
||||
import logging
|
||||
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db.models import Q
|
||||
from django.forms.models import ModelChoiceIterator
|
||||
from django.utils.encoding import force_unicode, smart_unicode
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from . import util
|
||||
from .util import extract_some_key_val
|
||||
from .views import NO_ERR_RESP
|
||||
from .widgets import AutoHeavySelect2Mixin # NOQA
|
||||
from .widgets import (AutoHeavySelect2MultipleWidget,
|
||||
AutoHeavySelect2TagWidget, AutoHeavySelect2Widget,
|
||||
HeavySelect2MultipleWidget, HeavySelect2TagWidget,
|
||||
HeavySelect2Widget, Select2MultipleWidget, Select2Widget)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
@ -41,11 +61,7 @@ class AutoViewFieldMixin(object):
|
|||
if logger.isEnabledFor(logging.INFO):
|
||||
logger.info("Registering auto field: %s", name)
|
||||
|
||||
from . import util
|
||||
|
||||
rf = util.register_field
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
rf = util.timer(rf)
|
||||
|
||||
id_ = rf(name, self)
|
||||
self.field_id = id_
|
||||
|
|
@ -70,29 +86,12 @@ class AutoViewFieldMixin(object):
|
|||
return True
|
||||
|
||||
def get_results(self, request, term, page, context):
|
||||
"See :py:meth:`.views.Select2View.get_results`."
|
||||
"""See :py:meth:`.views.Select2View.get_results`."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
import copy
|
||||
# ## Light general fields ##
|
||||
|
||||
from django import forms
|
||||
from django.core import validators
|
||||
from django.core.exceptions import ValidationError
|
||||
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, force_unicode
|
||||
|
||||
from .widgets import Select2Widget, Select2MultipleWidget,\
|
||||
HeavySelect2Widget, HeavySelect2MultipleWidget, AutoHeavySelect2Widget, \
|
||||
AutoHeavySelect2MultipleWidget, AutoHeavySelect2Mixin, AutoHeavySelect2TagWidget, \
|
||||
HeavySelect2TagWidget
|
||||
from .views import NO_ERR_RESP
|
||||
from .util import extract_some_key_val
|
||||
|
||||
|
||||
### Light general fields ###
|
||||
|
||||
class Select2ChoiceField(forms.ChoiceField):
|
||||
"""
|
||||
|
|
@ -108,7 +107,8 @@ class Select2MultipleChoiceField(forms.MultipleChoiceField):
|
|||
widget = Select2MultipleWidget
|
||||
|
||||
|
||||
### Model fields related mixins ###
|
||||
# ## Model fields related mixins ##
|
||||
|
||||
|
||||
class ModelResultJsonMixin(object):
|
||||
"""
|
||||
|
|
@ -273,9 +273,15 @@ class ModelResultJsonMixin(object):
|
|||
res = list(qs.filter(*params['or'], **params['and']).distinct())
|
||||
has_more = False
|
||||
|
||||
res = [(getattr(obj, self.to_field_name), self.label_from_instance(obj), self.extra_data_from_instance(obj))
|
||||
for obj in res]
|
||||
return (NO_ERR_RESP, has_more, res, )
|
||||
res = [
|
||||
(
|
||||
getattr(obj, self.to_field_name),
|
||||
self.label_from_instance(obj),
|
||||
self.extra_data_from_instance(obj)
|
||||
)
|
||||
for obj in res
|
||||
]
|
||||
return NO_ERR_RESP, has_more, res
|
||||
|
||||
|
||||
class UnhideableQuerysetType(type):
|
||||
|
|
@ -331,6 +337,7 @@ class ChoiceMixin(object):
|
|||
result._choices = copy.deepcopy(self._choices, memo)
|
||||
return result
|
||||
|
||||
|
||||
class FilterableModelChoiceIterator(ModelChoiceIterator):
|
||||
"""
|
||||
Extends ModelChoiceIterator to add the capability to apply additional
|
||||
|
|
@ -352,6 +359,7 @@ class FilterableModelChoiceIterator(ModelChoiceIterator):
|
|||
else:
|
||||
self.queryset = self._original_queryset
|
||||
|
||||
|
||||
class QuerysetChoiceMixin(ChoiceMixin):
|
||||
"""
|
||||
Overrides ``choices``' getter to return instance of :py:class:`.FilterableModelChoiceIterator`
|
||||
|
|
@ -381,6 +389,7 @@ class QuerysetChoiceMixin(ChoiceMixin):
|
|||
result.queryset = result.queryset
|
||||
return result
|
||||
|
||||
|
||||
class ModelChoiceFieldMixin(QuerysetChoiceMixin):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -411,7 +420,9 @@ class ModelChoiceFieldMixin(QuerysetChoiceMixin):
|
|||
def get_pk_field_name(self):
|
||||
return self.to_field_name or 'pk'
|
||||
|
||||
### Slightly altered versions of the Django counterparts with the same name in forms module. ###
|
||||
|
||||
# ## Slightly altered versions of the Django counterparts with the same name in forms module. ##
|
||||
|
||||
|
||||
class ModelChoiceField(ModelChoiceFieldMixin, forms.ModelChoiceField):
|
||||
queryset = property(ModelChoiceFieldMixin._get_queryset, forms.ModelChoiceField._set_queryset)
|
||||
|
|
@ -421,7 +432,7 @@ class ModelMultipleChoiceField(ModelChoiceFieldMixin, forms.ModelMultipleChoiceF
|
|||
queryset = property(ModelChoiceFieldMixin._get_queryset, forms.ModelMultipleChoiceField._set_queryset)
|
||||
|
||||
|
||||
### Light Fields specialized for Models ###
|
||||
# ## Light Fields specialized for Models ##
|
||||
|
||||
|
||||
class ModelSelect2Field(ModelChoiceField):
|
||||
|
|
@ -442,7 +453,8 @@ class ModelSelect2MultipleField(ModelMultipleChoiceField):
|
|||
widget = Select2MultipleWidget
|
||||
|
||||
|
||||
### Heavy fields ###
|
||||
# ## Heavy fields ##
|
||||
|
||||
|
||||
class HeavySelect2FieldBaseMixin(object):
|
||||
"""
|
||||
|
|
@ -469,10 +481,6 @@ class HeavySelect2FieldBaseMixin(object):
|
|||
be raised.
|
||||
|
||||
"""
|
||||
from . import util
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
t1 = util.timer_start('HeavySelect2FieldBaseMixin.__init__')
|
||||
|
||||
data_view = kwargs.pop('data_view', None)
|
||||
choices = kwargs.pop('choices', [])
|
||||
|
||||
|
|
@ -497,16 +505,10 @@ class HeavySelect2FieldBaseMixin(object):
|
|||
# Widget should have been instantiated by now.
|
||||
self.widget.field = self
|
||||
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
t2 = util.timer_start('HeavySelect2FieldBaseMixin.__init__:choices initialization')
|
||||
|
||||
# ModelChoiceField will set self.choices to ModelChoiceIterator
|
||||
if choices and not (hasattr(self, 'choices') and isinstance(self.choices, forms.models.ModelChoiceIterator)):
|
||||
self.choices = choices
|
||||
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
util.timer_end(t2)
|
||||
util.timer_end(t1)
|
||||
|
||||
class HeavyChoiceField(ChoiceMixin, forms.Field):
|
||||
"""
|
||||
|
|
@ -622,14 +624,15 @@ class HeavyMultipleChoiceField(HeavyChoiceField):
|
|||
|
||||
|
||||
class HeavySelect2ChoiceField(HeavySelect2FieldBaseMixin, HeavyChoiceField):
|
||||
"Heavy Select2 Choice field."
|
||||
"""Heavy Select2 Choice field."""
|
||||
widget = HeavySelect2Widget
|
||||
|
||||
|
||||
class HeavySelect2MultipleChoiceField(HeavySelect2FieldBaseMixin, HeavyMultipleChoiceField):
|
||||
"Heavy Select2 Multiple Choice field."
|
||||
"""Heavy Select2 Multiple Choice field."""
|
||||
widget = HeavySelect2MultipleWidget
|
||||
|
||||
|
||||
class HeavySelect2TagField(HeavySelect2MultipleChoiceField):
|
||||
"""
|
||||
Heavy Select2 field for tagging.
|
||||
|
|
@ -663,10 +666,12 @@ class HeavySelect2TagField(HeavySelect2MultipleChoiceField):
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
### Heavy field specialized for Models ###
|
||||
|
||||
# ## Heavy field specialized for Models ##
|
||||
|
||||
|
||||
class HeavyModelSelect2ChoiceField(HeavySelect2FieldBaseMixin, ModelChoiceField):
|
||||
"Heavy Select2 Choice field, specialized for Models."
|
||||
"""Heavy Select2 Choice field, specialized for Models."""
|
||||
widget = HeavySelect2Widget
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
|
@ -675,13 +680,14 @@ class HeavyModelSelect2ChoiceField(HeavySelect2FieldBaseMixin, ModelChoiceField)
|
|||
|
||||
|
||||
class HeavyModelSelect2MultipleChoiceField(HeavySelect2FieldBaseMixin, ModelMultipleChoiceField):
|
||||
"Heavy Select2 Multiple Choice field, specialized for Models."
|
||||
"""Heavy Select2 Multiple Choice field, specialized for Models."""
|
||||
widget = HeavySelect2MultipleWidget
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.pop('choices', None)
|
||||
super(HeavyModelSelect2MultipleChoiceField, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class HeavyModelSelect2TagField(HeavySelect2FieldBaseMixin, ModelMultipleChoiceField):
|
||||
"""
|
||||
Heavy Select2 field for tagging, specialized for Models.
|
||||
|
|
@ -695,12 +701,12 @@ class HeavyModelSelect2TagField(HeavySelect2FieldBaseMixin, ModelMultipleChoiceF
|
|||
super(HeavyModelSelect2TagField, self).__init__(*args, **kwargs)
|
||||
|
||||
def to_python(self, value):
|
||||
if value in EMPTY_VALUES:
|
||||
if value in self.empty_values:
|
||||
return None
|
||||
try:
|
||||
key = self.to_field_name or 'pk'
|
||||
value = self.queryset.get(**{key: value})
|
||||
except ValueError, e:
|
||||
except ValueError:
|
||||
raise ValidationError(self.error_messages['invalid_choice'])
|
||||
except self.queryset.model.DoesNotExist:
|
||||
value = self.create_new_value(value)
|
||||
|
|
@ -769,7 +775,8 @@ class HeavyModelSelect2TagField(HeavySelect2FieldBaseMixin, ModelMultipleChoiceF
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
### Heavy general field that uses central AutoView ###
|
||||
# ## Heavy general field that uses central AutoView ##
|
||||
|
||||
|
||||
class AutoSelect2Field(AutoViewFieldMixin, HeavySelect2ChoiceField):
|
||||
"""
|
||||
|
|
@ -796,6 +803,7 @@ class AutoSelect2MultipleField(AutoViewFieldMixin, HeavySelect2MultipleChoiceFie
|
|||
|
||||
widget = AutoHeavySelect2MultipleWidget
|
||||
|
||||
|
||||
class AutoSelect2TagField(AutoViewFieldMixin, HeavySelect2TagField):
|
||||
"""
|
||||
Auto Heavy Select2 field for tagging.
|
||||
|
|
@ -808,7 +816,9 @@ class AutoSelect2TagField(AutoViewFieldMixin, HeavySelect2TagField):
|
|||
|
||||
widget = AutoHeavySelect2TagWidget
|
||||
|
||||
### Heavy field, specialized for Model, that uses central AutoView ###
|
||||
|
||||
# ## Heavy field, specialized for Model, that uses central AutoView ##
|
||||
|
||||
|
||||
class AutoModelSelect2Field(ModelResultJsonMixin, AutoViewFieldMixin, HeavyModelSelect2ChoiceField):
|
||||
"""
|
||||
|
|
@ -837,6 +847,7 @@ class AutoModelSelect2MultipleField(ModelResultJsonMixin, AutoViewFieldMixin, He
|
|||
|
||||
widget = AutoHeavySelect2MultipleWidget
|
||||
|
||||
|
||||
class AutoModelSelect2TagField(ModelResultJsonMixin, AutoViewFieldMixin, HeavyModelSelect2TagField):
|
||||
"""
|
||||
Auto Heavy Select2 field for tagging, specialized for Models.
|
||||
|
|
|
|||
|
|
@ -1,21 +1,26 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import memcache
|
||||
|
||||
|
||||
class Client(object):
|
||||
host = ""
|
||||
server = ""
|
||||
expiry = 900
|
||||
|
||||
def __init__(self, hostname="127.0.0.1", port="11211", expiry=900):
|
||||
self.host = "%s:%s" % (hostname, port)
|
||||
self.server = memcache.Client([self.host])
|
||||
self.expiry = expiry
|
||||
|
||||
|
||||
def set(self, key, value):
|
||||
"""
|
||||
This method is used to set a new value
|
||||
in the memcache server.
|
||||
"""
|
||||
self.server.set(self.normalize_key(key), value, self.expiry)
|
||||
|
||||
|
||||
def get(self, key):
|
||||
"""
|
||||
This method is used to retrieve a value
|
||||
|
|
|
|||
|
|
@ -1,14 +1,21 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
|
||||
class Client(object):
|
||||
cache = None
|
||||
db = None
|
||||
|
||||
def __init__(self, hostname="127.0.0.1", port="11211", expiry=900):
|
||||
if hostname and port:
|
||||
import memcache_client
|
||||
|
||||
self.cache = memcache_client.Client(hostname, port, expiry)
|
||||
|
||||
|
||||
import db_client
|
||||
|
||||
self.db = db_client.Client()
|
||||
|
||||
|
||||
def set(self, key, value):
|
||||
"""
|
||||
This method is used to set a new value
|
||||
|
|
@ -17,7 +24,7 @@ class Client(object):
|
|||
self.db.set(key, value)
|
||||
if self.cache:
|
||||
self.cache.set(key, value)
|
||||
|
||||
|
||||
def get(self, key):
|
||||
"""
|
||||
This method is used to retrieve a value
|
||||
|
|
|
|||
|
|
@ -1,9 +1,15 @@
|
|||
from django.db import models
|
||||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.db import models
|
||||
from django.utils.encoding import force_text, python_2_unicode_compatible
|
||||
|
||||
|
||||
@python_2_unicode_compatible
|
||||
class KeyMap(models.Model):
|
||||
key = models.CharField(max_length=40, unique=True)
|
||||
value = models.CharField(max_length=100)
|
||||
accessed_on = models.DateTimeField(auto_now_add=True, auto_now=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode("%s => %s" % (self.key, self.value))
|
||||
def __str__(self):
|
||||
return force_text("%s => %s" % (self.key, self.value))
|
||||
|
|
|
|||
|
|
@ -1,32 +1,34 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django import template
|
||||
from django_select2.widgets import HeavySelect2Widget, Select2Widget
|
||||
|
||||
register = template.Library()
|
||||
|
||||
from ..widgets import HeavySelect2Widget, Select2Widget
|
||||
|
||||
__proxy_widget = HeavySelect2Widget(data_view="xyz")
|
||||
__proxy_light_widget = Select2Widget()
|
||||
|
||||
|
||||
@register.simple_tag(name='import_django_select2_js')
|
||||
def import_js(light=0):
|
||||
if light:
|
||||
return u'\n'.join(__proxy_light_widget.media.render_js())
|
||||
else:
|
||||
return u'\n'.join(__proxy_widget.media.render_js())
|
||||
if light:
|
||||
return u'\n'.join(__proxy_light_widget.media.render_js())
|
||||
else:
|
||||
return u'\n'.join(__proxy_widget.media.render_js())
|
||||
|
||||
|
||||
@register.simple_tag(name='import_django_select2_css')
|
||||
def import_css(light=0):
|
||||
if light:
|
||||
return u'\n'.join(__proxy_light_widget.media.render_css())
|
||||
else:
|
||||
return u'\n'.join(__proxy_widget.media.render_css())
|
||||
if light:
|
||||
return u'\n'.join(__proxy_light_widget.media.render_css())
|
||||
else:
|
||||
return u'\n'.join(__proxy_widget.media.render_css())
|
||||
|
||||
|
||||
@register.simple_tag(name='import_django_select2_js_css')
|
||||
def import_all(light=0):
|
||||
if light:
|
||||
return __proxy_light_widget.media.render()
|
||||
else:
|
||||
return __proxy_widget.media.render()
|
||||
if light:
|
||||
return __proxy_light_widget.media.render()
|
||||
else:
|
||||
return __proxy_widget.media.render()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
from django.conf.urls import *
|
||||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .views import AutoResponseView
|
||||
|
||||
urlpatterns = patterns("",
|
||||
url(r"^fields/auto.json$", AutoResponseView.as_view(), name="django_select2_central_json"),
|
||||
urlpatterns = patterns(
|
||||
"",
|
||||
url(r"^fields/auto.json$",
|
||||
AutoResponseView.as_view(), name="django_select2_central_json"),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import datetime
|
||||
import hashlib
|
||||
import logging
|
||||
import re
|
||||
import threading
|
||||
import types
|
||||
|
||||
from django.utils.encoding import force_unicode
|
||||
from . import __ENABLE_MULTI_PROCESS_SUPPORT as ENABLE_MULTI_PROCESS_SUPPORT
|
||||
from . import __GENERATE_RANDOM_ID as GENERATE_RANDOM_ID
|
||||
from . import __MEMCACHE_HOST as MEMCACHE_HOST
|
||||
from . import __MEMCACHE_PORT as MEMCACHE_PORT
|
||||
from . import __MEMCACHE_TTL as MEMCACHE_TTL
|
||||
from . import __SECRET_SALT as SECRET_SALT
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -30,15 +37,11 @@ def extract_some_key_val(dct, keys):
|
|||
return edct
|
||||
|
||||
|
||||
### Auto view helper utils ###
|
||||
# ## Auto view helper utils ##
|
||||
|
||||
from . import __ENABLE_MULTI_PROCESS_SUPPORT as ENABLE_MULTI_PROCESS_SUPPORT, \
|
||||
__MEMCACHE_HOST as MEMCACHE_HOST, __MEMCACHE_PORT as MEMCACHE_PORT, __MEMCACHE_TTL as MEMCACHE_TTL
|
||||
|
||||
from . import __GENERATE_RANDOM_ID as GENERATE_RANDOM_ID, __SECRET_SALT as SECRET_SALT
|
||||
|
||||
def synchronized(f):
|
||||
"Decorator to synchronize multiple calls to a functions."
|
||||
"""Decorator to synchronize multiple calls to a functions."""
|
||||
f.__lock__ = threading.Lock()
|
||||
|
||||
def synced_f(*args, **kwargs):
|
||||
|
|
@ -53,9 +56,9 @@ __id_store = {}
|
|||
# Field's key to generated Id mapping.
|
||||
__field_store = {}
|
||||
|
||||
|
||||
ID_PATTERN = r"[0-9_a-zA-Z.:+\- ]+"
|
||||
|
||||
|
||||
def is_valid_id(val):
|
||||
"""
|
||||
Checks if ``val`` is a valid generated Id.
|
||||
|
|
@ -71,10 +74,13 @@ def is_valid_id(val):
|
|||
else:
|
||||
return True
|
||||
|
||||
|
||||
if ENABLE_MULTI_PROCESS_SUPPORT:
|
||||
from memcache_wrapped_db_client import Client
|
||||
|
||||
remote_server = Client(MEMCACHE_HOST, str(MEMCACHE_PORT), MEMCACHE_TTL)
|
||||
|
||||
|
||||
@synchronized
|
||||
def register_field(key, field):
|
||||
"""
|
||||
|
|
@ -92,7 +98,8 @@ def register_field(key, field):
|
|||
"""
|
||||
global __id_store, __field_store
|
||||
|
||||
from fields import AutoViewFieldMixin
|
||||
from .fields import AutoViewFieldMixin
|
||||
|
||||
if not isinstance(field, AutoViewFieldMixin):
|
||||
raise ValueError('Field must extend AutoViewFieldMixin')
|
||||
|
||||
|
|
@ -110,7 +117,8 @@ def register_field(key, field):
|
|||
logger.info("Registering new field: %s; With actual id: %s", key, id_)
|
||||
|
||||
if ENABLE_MULTI_PROCESS_SUPPORT:
|
||||
logger.info("Multi process support is enabled. Adding id-key mapping to remote server.")
|
||||
logger.info(
|
||||
"Multi process support is enabled. Adding id-key mapping to remote server.")
|
||||
remote_server.set(id_, key)
|
||||
else:
|
||||
id_ = __field_store[key]
|
||||
|
|
@ -144,31 +152,3 @@ def get_field(id_):
|
|||
else:
|
||||
logger.error('Unknown id "%s".', id_)
|
||||
return field
|
||||
|
||||
def timer_start(name):
|
||||
import sys, time
|
||||
if sys.platform == "win32":
|
||||
# On Windows, the best timer is time.clock()
|
||||
default_timer = time.clock
|
||||
multiplier = 1.0
|
||||
else:
|
||||
# On most other platforms the best timer is time.time()
|
||||
default_timer = time.time
|
||||
multiplier = 1000.0
|
||||
|
||||
return (name, default_timer, multiplier, default_timer())
|
||||
|
||||
def timer_end(t):
|
||||
(name, default_timer, multiplier, timeS) = t
|
||||
timeE = default_timer()
|
||||
logger.debug("Time taken by %s: %0.3f ms" % (name, (timeE - timeS) * multiplier))
|
||||
|
||||
def timer(f):
|
||||
def inner(*args, **kwargs):
|
||||
|
||||
t = timer_start(f.func_name)
|
||||
ret = f(*args, **kwargs)
|
||||
timer_end(t)
|
||||
|
||||
return ret
|
||||
return inner
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import json
|
||||
|
||||
from django.http import HttpResponse
|
||||
from django.views.generic import View
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.http import Http404
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.views.generic import View
|
||||
|
||||
from .util import get_field, is_valid_id
|
||||
|
||||
|
|
@ -14,6 +16,7 @@ Equals to 'nil' constant.
|
|||
Use this in :py:meth:`.Select2View.get_results` to mean no error, instead of hardcoding 'nil' value.
|
||||
"""
|
||||
|
||||
|
||||
class JSONResponseMixin(object):
|
||||
"""
|
||||
A mixin that can be used to render a JSON response.
|
||||
|
|
@ -31,9 +34,10 @@ class JSONResponseMixin(object):
|
|||
)
|
||||
|
||||
def convert_context_to_json(self, context):
|
||||
"Convert the context dictionary into a JSON object"
|
||||
"""Convert the context dictionary into a JSON object"""
|
||||
return json.dumps(context)
|
||||
|
||||
|
||||
class Select2View(JSONResponseMixin, View):
|
||||
"""
|
||||
Base view which is designed to respond with JSON to Ajax queries from heavy widgets/fields.
|
||||
|
|
@ -98,7 +102,7 @@ class Select2View(JSONResponseMixin, View):
|
|||
if err == NO_ERR_RESP:
|
||||
for result in results:
|
||||
id_, text = result[:2]
|
||||
if len(result)>2:
|
||||
if len(result) > 2:
|
||||
extra_data = result[2]
|
||||
else:
|
||||
extra_data = {}
|
||||
|
|
@ -190,5 +194,3 @@ class AutoResponseView(Select2View):
|
|||
field = request.__django_select2_local
|
||||
del request.__django_select2_local
|
||||
return field.get_results(request, term, page, context)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
# -*- coding:utf-8 -*-
|
||||
"""
|
||||
Contains all the Django widgets for Select2.
|
||||
"""
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import json
|
||||
import logging
|
||||
from itertools import chain
|
||||
import re
|
||||
import util
|
||||
from itertools import chain
|
||||
|
||||
from django import forms
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.validators import EMPTY_VALUES
|
||||
from django.utils.datastructures import MergeDict, MultiValueDict
|
||||
from django.utils.encoding import force_unicode
|
||||
from django.utils.safestring import mark_safe
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.utils.datastructures import MultiValueDict, MergeDict
|
||||
from django.utils.six import text_type
|
||||
|
||||
from . import __RENDER_SELECT2_STATICS as RENDER_SELECT2_STATICS
|
||||
|
||||
|
|
@ -26,6 +29,7 @@ def get_select2_js_libs():
|
|||
else:
|
||||
return ('js/select2.min.js', )
|
||||
|
||||
|
||||
def get_select2_heavy_js_libs():
|
||||
libs = get_select2_js_libs()
|
||||
|
||||
|
|
@ -35,6 +39,7 @@ def get_select2_heavy_js_libs():
|
|||
else:
|
||||
return libs + ('js/heavy_data.min.js', )
|
||||
|
||||
|
||||
def get_select2_css_libs(light=False):
|
||||
from django.conf import settings
|
||||
from . import __BOOTSTRAP
|
||||
|
|
@ -61,7 +66,9 @@ def get_select2_css_libs(light=False):
|
|||
else:
|
||||
return ('css/all.min.css',)
|
||||
|
||||
### Light mixin and widgets ###
|
||||
|
||||
# ## Light mixin and widgets ##
|
||||
|
||||
|
||||
class Select2Mixin(object):
|
||||
"""
|
||||
|
|
@ -228,24 +235,18 @@ class Select2Mixin(object):
|
|||
:return: The rendered markup.
|
||||
:rtype: :py:obj:`unicode`
|
||||
"""
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
t1 = util.timer_start('Select2Mixin.render')
|
||||
|
||||
args = [name, value, attrs]
|
||||
if choices:
|
||||
args.append(choices)
|
||||
|
||||
s = unicode(super(Select2Mixin, self).render(*args)) # Thanks to @ouhouhsami Issue#1
|
||||
s = text_type(super(Select2Mixin, self).render(*args)) # Thanks to @ouhouhsami Issue#1
|
||||
if RENDER_SELECT2_STATICS:
|
||||
s += self.media.render()
|
||||
final_attrs = self.build_attrs(attrs)
|
||||
id_ = final_attrs.get('id', None)
|
||||
s += self.render_js_code(id_, name, value, attrs, choices)
|
||||
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
util.timer_end(t1)
|
||||
logger.debug("Generated widget code:-\n%s", s)
|
||||
|
||||
return mark_safe(s)
|
||||
|
||||
class Media:
|
||||
|
|
@ -268,10 +269,10 @@ class Select2Widget(Select2Mixin, forms.Select):
|
|||
|
||||
def render_options(self, choices, selected_choices):
|
||||
all_choices = chain(self.choices, choices)
|
||||
if not self.is_required and \
|
||||
len([value for value, txt in all_choices if value == '']) == 0: # Checking if list already has empty choice
|
||||
# as in the case of Model based Light fields.
|
||||
|
||||
if not self.is_required \
|
||||
and len([value for value, txt in all_choices if value == '']) == 0:
|
||||
# Checking if list already has empty choice
|
||||
# as in the case of Model based Light fields.
|
||||
choices = list(choices)
|
||||
choices.append(('', '', )) # Adding an empty choice
|
||||
return super(Select2Widget, self).render_options(choices, selected_choices)
|
||||
|
|
@ -295,7 +296,9 @@ class Select2MultipleWidget(Select2Mixin, forms.SelectMultiple):
|
|||
self.options.pop('minimumResultsForSearch', None)
|
||||
|
||||
|
||||
### Specialized Multiple Hidden Input Widget ###
|
||||
# ## Specialized Multiple Hidden Input Widget ##
|
||||
|
||||
|
||||
class MultipleSelect2HiddenInput(forms.TextInput):
|
||||
"""
|
||||
Multiple hidden input for Select2.
|
||||
|
|
@ -338,7 +341,9 @@ class MultipleSelect2HiddenInput(forms.TextInput):
|
|||
data_set = set([force_unicode(value) for value in data])
|
||||
return data_set != initial_set
|
||||
|
||||
### Heavy mixins and widgets ###
|
||||
|
||||
# ## Heavy mixins and widgets ##
|
||||
|
||||
|
||||
class HeavySelect2Mixin(Select2Mixin):
|
||||
"""
|
||||
|
|
@ -617,7 +622,8 @@ class HeavySelect2TagWidget(HeavySelect2MultipleWidget):
|
|||
return js
|
||||
|
||||
|
||||
### Auto Heavy widgets ###
|
||||
# ## Auto Heavy widgets ##
|
||||
|
||||
|
||||
class AutoHeavySelect2Mixin(object):
|
||||
"""
|
||||
|
|
@ -660,14 +666,15 @@ class AutoHeavySelect2Mixin(object):
|
|||
|
||||
|
||||
class AutoHeavySelect2Widget(AutoHeavySelect2Mixin, HeavySelect2Widget):
|
||||
"Auto version of :py:class:`.HeavySelect2Widget`"
|
||||
"""Auto version of :py:class:`.HeavySelect2Widget`"""
|
||||
pass
|
||||
|
||||
|
||||
class AutoHeavySelect2MultipleWidget(AutoHeavySelect2Mixin, HeavySelect2MultipleWidget):
|
||||
"Auto version of :py:class:`.HeavySelect2MultipleWidget`"
|
||||
"""Auto version of :py:class:`.HeavySelect2MultipleWidget`"""
|
||||
pass
|
||||
|
||||
|
||||
class AutoHeavySelect2TagWidget(AutoHeavySelect2Mixin, HeavySelect2TagWidget):
|
||||
"Auto version of :py:class:`.HeavySelect2TagWidget`"
|
||||
"""Auto version of :py:class:`.HeavySelect2TagWidget`"""
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
[pytest]
|
||||
norecursedirs=env testapp django_select2 docs
|
||||
norecursedirs=env testapp docs
|
||||
addopts = --tb=short --pep8 --flakes -rxs
|
||||
pep8maxlinelength=139
|
||||
pep8ignore=
|
||||
flakes-ignore=
|
||||
django_select2/__init__.py UnusedImport
|
||||
django_select2/fields.py UnusedImport
|
||||
|
|
|
|||
|
|
@ -3,4 +3,5 @@ pytest-pep8
|
|||
pytest-flakes
|
||||
pytest-django
|
||||
selenium
|
||||
model_mommy
|
||||
model_mommy
|
||||
isort
|
||||
Loading…
Reference in a new issue