diff --git a/django_select2/conf.py b/django_select2/conf.py index 03ebe7dd..0f34f774 100644 --- a/django_select2/conf.py +++ b/django_select2/conf.py @@ -4,13 +4,12 @@ __all__ = ("settings", "Select2Conf") +from django.contrib.admin.widgets import SELECT2_TRANSLATIONS + class Select2Conf(AppConf): """Settings for Django-Select2.""" - LIB_VERSION = "4.0.12" - """Version of the Select2 library.""" - CACHE_BACKEND = "default" """ Django-Select2 uses Django's cache to sure a consistent state across multiple machines. @@ -56,11 +55,9 @@ class Select2Conf(AppConf): It has set `select2_` as a default value, which you can change if needed. """ - JS = "https://cdnjs.cloudflare.com/ajax/libs/select2/{version}/js/select2.min.js".format( - version=LIB_VERSION - ) + JS = "admin/js/vendor/select2/select2.full.min.js" """ - The URI for the Select2 JS file. By default this points to the Cloudflare CDN. + The URI for the Select2 JS file. By default this points to version shipped with Django. If you want to select the version of the JS library used, or want to serve it from the local 'static' resources, add a line to your settings.py like so:: @@ -76,11 +73,9 @@ class Select2Conf(AppConf): develop without an Internet connection. """ - CSS = "https://cdnjs.cloudflare.com/ajax/libs/select2/{version}/css/select2.min.css".format( - version=LIB_VERSION - ) + CSS = "admin/css/vendor/select2/select2.min.css" """ - The URI for the Select2 CSS file. By default this points to the Cloudflare CDN. + The URI for the Select2 CSS file. By default this points to version shipped with Django. If you want to select the version of the library used, or want to serve it from the local 'static' resources, add a line to your settings.py like so:: @@ -112,13 +107,9 @@ class Select2Conf(AppConf): .. tip:: When using other themes, you may need use select2 css and theme css. """ - I18N_PATH = ( - "https://cdnjs.cloudflare.com/ajax/libs/select2/{version}/js/i18n".format( - version=LIB_VERSION - ) - ) + I18N_PATH = "admin/js/vendor/select2/i18n" """ - The base URI for the Select2 i18n files. By default this points to the Cloudflare CDN. + The base URI for the Select2 i18n files. By default this points to version shipped with Django. If you want to select the version of the I18N library used, or want to serve it from the local 'static' resources, add a line to your settings.py like so:: @@ -129,55 +120,7 @@ class Select2Conf(AppConf): develop without an Internet connection. """ - I18N_AVAILABLE_LANGUAGES = [ - "ar", - "az", - "bg", - "ca", - "cs", - "da", - "de", - "el", - "en", - "es", - "et", - "eu", - "fa", - "fi", - "fr", - "gl", - "he", - "hi", - "hr", - "hu", - "id", - "is", - "it", - "ja", - "km", - "ko", - "lt", - "lv", - "mk", - "ms", - "nb", - "nl", - "pl", - "pt-BR", - "pt", - "ro", - "ru", - "sk", - "sr-Cyrl", - "sr", - "sv", - "th", - "tr", - "uk", - "vi", - "zh-CN", - "zh-TW", - ] + I18N_AVAILABLE_LANGUAGES = list(SELECT2_TRANSLATIONS.values()) """ List of available translations. diff --git a/django_select2/forms.py b/django_select2/forms.py index 68be213f..4809d066 100644 --- a/django_select2/forms.py +++ b/django_select2/forms.py @@ -16,7 +16,7 @@ have to be pre-rendered onto the page and JavaScript would be used to search through them. Said that, they are also one - the most easiest to use. They are a + the easiest to use. They are a drop-in-replacement for Django's default select widgets. @@ -293,7 +293,7 @@ def render(self, *args, **kwargs): return output def _get_cache_key(self): - return "%s%s" % (settings.SELECT2_CACHE_PREFIX, self.uuid) + return f"{settings.SELECT2_CACHE_PREFIX}{self.uuid}" def set_to_cache(self): """ diff --git a/django_select2/static/django_select2/django_select2.js b/django_select2/static/django_select2/django_select2.js index f2358df0..01db20b5 100644 --- a/django_select2/static/django_select2/django_select2.js +++ b/django_select2/static/django_select2/django_select2.js @@ -6,7 +6,7 @@ module.exports = factory(require('jquery')) } else { // Browser globals - factory(jQuery) + factory(jQuery || window.django.jQuery) } }(function ($) { 'use strict' diff --git a/django_select2/views.py b/django_select2/views.py index 1665dbd5..66fdc420 100644 --- a/django_select2/views.py +++ b/django_select2/views.py @@ -92,7 +92,7 @@ def get_widget_or_404(self): except BadSignature: raise Http404('Invalid "field_id".') else: - cache_key = "%s%s" % (settings.SELECT2_CACHE_PREFIX, key) + cache_key = f"{settings.SELECT2_CACHE_PREFIX}{key}" widget_dict = cache.get(cache_key) if widget_dict is None: raise Http404("field_id not found") diff --git a/docs/extra.rst b/docs/extra.rst index 0865d77c..4de25275 100644 --- a/docs/extra.rst +++ b/docs/extra.rst @@ -39,7 +39,7 @@ the field in the form. The value represents the name of the field in the model ( class AddressForm(forms.Form): country = forms.ModelChoiceField( queryset=Country.objects.all(), - label=u"Country", + label="Country", widget=ModelSelect2Widget( model=Country, search_fields=['name__icontains'], @@ -48,7 +48,7 @@ the field in the form. The value represents the name of the field in the model ( city = forms.ModelChoiceField( queryset=City.objects.all(), - label=u"City", + label="City", widget=ModelSelect2Widget( model=City, search_fields=['name__icontains'], @@ -72,7 +72,7 @@ Customize the form in a manner: class AddressForm(forms.Form): country = forms.ModelChoiceField( queryset=Country.objects.all(), - label=u"Country", + label="Country", widget=ModelSelect2Widget( search_fields=['name__icontains'], dependent_fields={'city': 'cities'}, @@ -81,7 +81,7 @@ Customize the form in a manner: city = forms.ModelChoiceField( queryset=City.objects.all(), - label=u"City", + label="City", widget=ModelSelect2Widget( search_fields=['name__icontains'], dependent_fields={'country': 'country'}, diff --git a/docs/index.rst b/docs/index.rst index 6ba1f8f3..35454f9c 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,6 +8,16 @@ Install ``django-select2``:: python3 -m pip install django-select2 Add ``django_select2`` to your ``INSTALLED_APPS`` in your project settings. +Since version 8, please ensure that Django's admin app is enabled too: + +.. code-block:: python + + INSTALLED_APPS = [ + # other django apps… + 'django.contrib.admin', + # other 3rd party apps… + 'django_select2', + ] Add ``django_select`` to your URL root configuration: @@ -16,20 +26,20 @@ Add ``django_select`` to your URL root configuration: from django.urls import include, path urlpatterns = [ - # … other patterns + # other patterns… path("select2/", include("django_select2.urls")), - # … other patterns + # other patterns… ] ``django-select2`` requires a cache backend which is **persistent** -across all application servers.. +across all application servers.. **This means that the** :class:`.DummyCache` **backend will not work!** The default cache backend is :class:`.LocMemCache`, which is persistent across a single node. For projects with a single application server -this will work fine, however you will run into issues when +this will work fine, however you will run into issues when you scale up into multiple servers. Below is an example setup using Redis, which is a solution that diff --git a/example/example/settings.py b/example/example/settings.py index 7e629a6e..6eef77a3 100644 --- a/example/example/settings.py +++ b/example/example/settings.py @@ -117,14 +117,12 @@ CACHES = { "default": { - "BACKEND": "django_redis.cache.RedisCache", + "BACKEND": "django.core.cache.backends.redis.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", - "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, }, "select2": { - "BACKEND": "django_redis.cache.RedisCache", + "BACKEND": "django.core.cache.backends.redis.RedisCache", "LOCATION": "redis://127.0.0.1:6379/2", - "OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient"}, }, } diff --git a/example/example/templates/example/book_form.html b/example/example/templates/example/book_form.html index c2ff60bf..daea5304 100644 --- a/example/example/templates/example/book_form.html +++ b/example/example/templates/example/book_form.html @@ -1,4 +1,4 @@ - +{% load static %} Create Book @@ -14,7 +14,7 @@

Create a new Book

{{ form.as_p }} - + {{ form.media.js }} diff --git a/example/requirements.txt b/example/requirements.txt index 53500ba2..b93550d1 100644 --- a/example/requirements.txt +++ b/example/requirements.txt @@ -1,2 +1,2 @@ -e .. -django-redis +redis diff --git a/tests/test_forms.py b/tests/test_forms.py index 0b7c0af7..a3a0d8b5 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -13,7 +13,6 @@ from selenium.webdriver.support.wait import WebDriverWait from django_select2.cache import cache -from django_select2.conf import settings from django_select2.forms import ( HeavySelect2MultipleWidget, HeavySelect2Widget, @@ -135,28 +134,28 @@ def test_empty_option(self, db): def test_i18n(self): translation.activate("de") assert tuple(Select2Widget().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/i18n/de.js", + "admin/js/vendor/select2/select2.full.min.js", + "admin/js/vendor/select2/i18n/de.js", "django_select2/django_select2.js", ) translation.activate("en") assert tuple(Select2Widget().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/i18n/en.js", + "admin/js/vendor/select2/select2.full.min.js", + "admin/js/vendor/select2/i18n/en.js", "django_select2/django_select2.js", ) translation.activate("00") assert tuple(Select2Widget().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", + "admin/js/vendor/select2/select2.full.min.js", "django_select2/django_select2.js", ) - translation.activate("sr-cyrl") + translation.activate("sr-Cyrl") assert tuple(Select2Widget().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/i18n/sr-Cyrl.js", + "admin/js/vendor/select2/select2.full.min.js", + "admin/js/vendor/select2/i18n/sr-Cyrl.js", "django_select2/django_select2.js", ) @@ -164,15 +163,15 @@ def test_i18n(self): translation.activate("zh-hans") assert tuple(Select2Widget().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/i18n/zh-CN.js", + "admin/js/vendor/select2/select2.full.min.js", + "admin/js/vendor/select2/i18n/zh-CN.js", "django_select2/django_select2.js", ) translation.activate("zh-hant") assert tuple(Select2Widget().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/i18n/zh-TW.js", + "admin/js/vendor/select2/select2.full.min.js", + "admin/js/vendor/select2/i18n/zh-TW.js", "django_select2/django_select2.js", ) @@ -186,8 +185,8 @@ class TestSelect2AdminMixin: def test_media(self): translation.activate("en") assert tuple(Select2AdminMixin().media._js) == ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js", - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/i18n/en.js", + "admin/js/vendor/select2/select2.full.min.js", + "admin/js/vendor/select2/i18n/en.js", "django_select2/django_select2.js", ) @@ -204,14 +203,8 @@ class TestSelect2MixinSettings: def test_default_media(self): sut = Select2Widget() result = sut.media.render() - assert ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/js/select2.min.js" - in result - ) - assert ( - f"https://cdnjs.cloudflare.com/ajax/libs/select2/{settings.SELECT2_LIB_VERSION}/css/select2.min.css" - in result - ) + assert "admin/js/vendor/select2/select2.full.min.js" in result + assert "admin/css/vendor/select2/select2.min.css" in result assert "django_select2/django_select2.js" in result def test_js_setting(self, settings): diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py index 15b29b59..f6673aa9 100644 --- a/tests/testapp/settings.py +++ b/tests/testapp/settings.py @@ -12,6 +12,7 @@ "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.staticfiles", + "django.contrib.admin", "django_select2", "tests.testapp", ) diff --git a/tests/testapp/templates/form.html b/tests/testapp/templates/form.html index 7499bc8e..bd817eb2 100644 --- a/tests/testapp/templates/form.html +++ b/tests/testapp/templates/form.html @@ -1,6 +1,5 @@ -{% load static %} - - +{% load static %} + {{ form.media.css }}