From d27760e4e2b58b929aa9dad98d4c954c4c558e6e Mon Sep 17 00:00:00 2001
From: Johannes Hoppe <info@johanneshoppe.com>
Date: Sun, 24 May 2020 18:10:58 +0200
Subject: [PATCH 001/168] Fix NPM release version

---
 .github/workflows/release.yml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3a25ac0e..2a425c4f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,6 +24,8 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v1
+      - uses: actions/setup-python@v1
+      - run: python set_version.py
       - uses: actions/checkout@v2
       - name: Upload packages
         run: npm publish

From 35354d0f9fcc19725f61e15c5d6fc65a24ff3615 Mon Sep 17 00:00:00 2001
From: Johannes Hoppe <info@johanneshoppe.com>
Date: Sun, 24 May 2020 18:27:00 +0200
Subject: [PATCH 002/168] Fix NPM release command

---
 .github/workflows/release.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 2a425c4f..699b3186 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -25,8 +25,8 @@ jobs:
     steps:
       - uses: actions/setup-node@v1
       - uses: actions/setup-python@v1
-      - run: python set_version.py
       - uses: actions/checkout@v2
+      - run: python set_version.py
       - name: Upload packages
         run: npm publish
         env:

From b9d02bc5bc1e4c284277b28b1ecb5f3763f5b972 Mon Sep 17 00:00:00 2001
From: Johannes Hoppe <info@johanneshoppe.com>
Date: Thu, 28 May 2020 12:09:18 +0200
Subject: [PATCH 003/168] Fix code block syntax, thx @hartwork

---
 docs/index.rst | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/docs/index.rst b/docs/index.rst
index c27598a6..6f8b0d26 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,9 +3,7 @@
 Installation
 ------------
 
-Install ``django-select2``
-
-.. code-block:: python
+Install ``django-select2``::
 
     python3 -m pip install django-select2
 

From 5356c7cafa2503260d48a23e1bb1db8cb59b17dd Mon Sep 17 00:00:00 2001
From: Ian Campbell <ipcampbell@gmail.com>
Date: Tue, 8 Sep 2020 08:01:48 -0400
Subject: [PATCH 004/168] Clarify the key-value pair for the dependent_fields
 docs.

---
 docs/extra.rst | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/docs/extra.rst b/docs/extra.rst
index 664fe202..c3524ce7 100644
--- a/docs/extra.rst
+++ b/docs/extra.rst
@@ -27,10 +27,11 @@ Here are our two models:
 Customizing a Form
 ``````````````````
 
-Lets link two widgets via *dependent_fields*.
+Lets link two widgets via a *dependent_fields* dictionary. The key represents the name of 
+the field in the form. The value represents the name of the field in the model (used in `queryset`).
 
 .. code-block:: python
-    :emphasize-lines: 15
+    :emphasize-lines: 17
 
     class AddressForm(forms.Form):
         country = forms.ModelChoiceField(

From f5a9d48d8c5e99258e5ff72f6d531da45e45c17a Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 11:02:55 +0100
Subject: [PATCH 005/168] Fix black code style

---
 .fussyfox.yml            |  1 +
 .github/workflows/ci.yml |  9 ---------
 django_select2/conf.py   |  6 ++++--
 tests/test_forms.py      | 31 ++++++++++++++++++-------------
 tests/testapp/forms.py   |  6 ++++--
 5 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/.fussyfox.yml b/.fussyfox.yml
index 600df195..6a17e6bd 100644
--- a/.fussyfox.yml
+++ b/.fussyfox.yml
@@ -1,4 +1,5 @@
 - bandit
+- black
 - flake8
 - isort
 - pydocstyle
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bf58dc22..de7a51fb 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,14 +7,6 @@ on:
 
 jobs:
 
-  black:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/setup-python@v2
-      - uses: actions/checkout@v2
-      - run: python -m pip install black
-      - run: black --check --diff .
-
   dist:
     runs-on: ubuntu-latest
     steps:
@@ -46,7 +38,6 @@ jobs:
   pytest:
     needs:
       - standardjs
-      - black
     strategy:
       matrix:
         python-version:
diff --git a/django_select2/conf.py b/django_select2/conf.py
index 3896fb62..4d686005 100644
--- a/django_select2/conf.py
+++ b/django_select2/conf.py
@@ -96,8 +96,10 @@ class Select2Conf(AppConf):
         develop without an Internet connection.
     """
 
-    I18N_PATH = "https://cdnjs.cloudflare.com/ajax/libs/select2/{version}/js/i18n".format(
-        version=LIB_VERSION
+    I18N_PATH = (
+        "https://cdnjs.cloudflare.com/ajax/libs/select2/{version}/js/i18n".format(
+            version=LIB_VERSION
+        )
     )
     """
     The base URI for the Select2 i18n files. By default this points to the Cloudflare CDN.
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 89ef8b69..1f02c828 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -222,26 +222,29 @@ def test_initial_form_class(self):
     def test_selected_option(self, db):
         not_required_field = self.form.fields["primary_genre"]
         assert not_required_field.required is False
-        assert '<option value="1" selected="selected">One</option>' in not_required_field.widget.render(
-            "primary_genre", 1
-        ) or '<option value="1" selected>One</option>' in not_required_field.widget.render(
-            "primary_genre", 1
-        ), not_required_field.widget.render(
-            "primary_genre", 1
-        )
+        assert (
+            '<option value="1" selected="selected">One</option>'
+            in not_required_field.widget.render("primary_genre", 1)
+            or '<option value="1" selected>One</option>'
+            in not_required_field.widget.render("primary_genre", 1)
+        ), (not_required_field.widget.render("primary_genre", 1))
 
     def test_many_selected_option(self, db, genres):
         field = HeavySelect2MultipleWidgetForm().fields["genres"]
         field.widget.choices = NUMBER_CHOICES
         widget_output = field.widget.render("genres", [1, 2])
-        selected_option = '<option value="{pk}" selected="selected">{value}</option>'.format(
-            pk=1, value="One"
+        selected_option = (
+            '<option value="{pk}" selected="selected">{value}</option>'.format(
+                pk=1, value="One"
+            )
         )
         selected_option_a = '<option value="{pk}" selected>{value}</option>'.format(
             pk=1, value="One"
         )
-        selected_option2 = '<option value="{pk}" selected="selected">{value}</option>'.format(
-            pk=2, value="Two"
+        selected_option2 = (
+            '<option value="{pk}" selected="selected">{value}</option>'.format(
+                pk=2, value="Two"
+            )
         )
         selected_option2a = '<option value="{pk}" selected>{value}</option>'.format(
             pk=2, value="Two"
@@ -334,8 +337,10 @@ def test_selected_option(self, db, genres):
         not_required_field = self.form.fields["primary_genre"]
         assert not_required_field.required is False
         widget_output = not_required_field.widget.render("primary_genre", genre.pk)
-        selected_option = '<option value="{pk}" selected="selected">{value}</option>'.format(
-            pk=genre.pk, value=force_str(genre)
+        selected_option = (
+            '<option value="{pk}" selected="selected">{value}</option>'.format(
+                pk=genre.pk, value=force_str(genre)
+            )
         )
         selected_option_a = '<option value="{pk}" selected>{value}</option>'.format(
             pk=genre.pk, value=force_str(genre)
diff --git a/tests/testapp/forms.py b/tests/testapp/forms.py
index 5fa245d9..da9487c5 100644
--- a/tests/testapp/forms.py
+++ b/tests/testapp/forms.py
@@ -111,7 +111,8 @@ class ArtistModelSelect2MultipleWidgetForm(forms.Form):
     title = forms.CharField(max_length=50)
     genres = forms.ModelMultipleChoiceField(
         widget=ModelSelect2MultipleWidget(
-            queryset=models.Genre.objects.all(), search_fields=["title__icontains"],
+            queryset=models.Genre.objects.all(),
+            search_fields=["title__icontains"],
         ),
         queryset=models.Genre.objects.all(),
         required=True,
@@ -119,7 +120,8 @@ class ArtistModelSelect2MultipleWidgetForm(forms.Form):
 
     featured_artists = forms.ModelMultipleChoiceField(
         widget=ModelSelect2MultipleWidget(
-            queryset=models.Artist.objects.all(), search_fields=["title__icontains"],
+            queryset=models.Artist.objects.all(),
+            search_fields=["title__icontains"],
         ),
         queryset=models.Artist.objects.all(),
         required=False,

From 4e7bbad45347653b6bb713ec41fcdb6aa896616d Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 11:26:26 +0100
Subject: [PATCH 006/168] Fix docs build

---
 .github/workflows/ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index de7a51fb..3ced4594 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -30,6 +30,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-python@v2
+      - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v2
       - run: sudo apt-get install -y gettext graphviz
       - run: python setup.py develop

From 98c9c45def8989c0d0fea19e8d58bacb90a98225 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 11:58:33 +0100
Subject: [PATCH 007/168] Fix bandit config

---
 .bandit                     | 2 +-
 example/example/settings.py | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.bandit b/.bandit
index fba0d25d..b7df1762 100644
--- a/.bandit
+++ b/.bandit
@@ -1,2 +1,2 @@
 [bandit]
-exclude: tests
+exclude: ./tests
diff --git a/example/example/settings.py b/example/example/settings.py
index 83067236..7e629a6e 100644
--- a/example/example/settings.py
+++ b/example/example/settings.py
@@ -20,7 +20,7 @@
 # See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/
 
 # SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = "kstexlapcf3lucx@47mmxsu9-9eixia+6n97aw)4$qo&!laxad"
+SECRET_KEY = "kstexlapcf3lucx@47mmxsu9-9eixia+6n97aw)4$qo&!laxad"  # nosec
 
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True

From 6ad44479d3aeba7bae4d9b5d069598fb705222b1 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 11:59:31 +0100
Subject: [PATCH 008/168] Add Python 3.9 support

---
 .github/workflows/ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3ced4594..913ff011 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -45,6 +45,7 @@ jobs:
           - "3.6"
           - "3.7"
           - "3.8"
+          - "3.9"
         django-version:
           - "2.2"
           - "3.0"

From 15629f4bb5b705465e2e5d4118d4d91afb0dcea0 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 11:59:44 +0100
Subject: [PATCH 009/168] Remove official Python 3.6 support

---
 .github/workflows/ci.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 913ff011..144fecc3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,6 @@ jobs:
     strategy:
       matrix:
         python-version:
-          - "3.6"
           - "3.7"
           - "3.8"
           - "3.9"

From 0e1b8c4671721d48fe13fb438150c810ba97f3f5 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 12:00:07 +0100
Subject: [PATCH 010/168] Add official Django 3.1 support

---
 .github/workflows/ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 144fecc3..5e8cdf0e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -48,6 +48,7 @@ jobs:
         django-version:
           - "2.2"
           - "3.0"
+          - "3.1"
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}

From 9cb9848dfe5faacef9077f2a0efd1ca97bc2fd0a Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 15 Dec 2020 12:02:32 +0100
Subject: [PATCH 011/168] Remove official Django 3.0 support

---
 .github/workflows/ci.yml | 1 -
 1 file changed, 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5e8cdf0e..bf69a668 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -47,7 +47,6 @@ jobs:
           - "3.9"
         django-version:
           - "2.2"
-          - "3.0"
           - "3.1"
     runs-on: ubuntu-latest
     steps:

From 709ec195504a0028ca053845d6e62886e7198f01 Mon Sep 17 00:00:00 2001
From: Jan Pieter Waagmeester <jieter@jieter.nl>
Date: Mon, 26 Oct 2020 15:58:21 +0100
Subject: [PATCH 012/168] Remove colon in example for use with ArrayField

---
 django_select2/forms.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 1f5554b9..0fedc39d 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -178,7 +178,7 @@ class Select2TagWidget(Select2TagMixin, Select2Mixin, forms.SelectMultiple):
         class MyWidget(Select2TagWidget):
 
             def value_from_datadict(self, data, files, name):
-                values = super().value_from_datadict(data, files, name):
+                values = super().value_from_datadict(data, files, name)
                 return ",".join(values)
 
             def optgroups(self, name, value, attrs=None):

From 07054b2d8ff15144c6b1b00577f3c898d47712bc Mon Sep 17 00:00:00 2001
From: David Bramwell <david.bramwell@wearesponge.com>
Date: Tue, 5 Jan 2021 11:36:35 +0000
Subject: [PATCH 013/168] Split search terms only for __contains queries

Split search terms only for `__contains` queries and not for
`__startswith` or `__endswith`. We no also split not only be
whitespace but tab and newline.

If multiple search fields are defined conditions combined with
and OR. If single word matches in a for contains queries are
OR combined as well.

Co-Authored-By: codingjoe <info@johanneshoppe.com>
---
 django_select2/forms.py | 21 +++++++++++--------
 tests/test_forms.py     | 46 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 0fedc39d..32d4ba11 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -46,8 +46,8 @@
     :parts: 1
 
 """
+import re
 import uuid
-from functools import reduce
 from itertools import chain
 from pickle import PicklingError  # nosec
 
@@ -315,6 +315,8 @@ class HeavySelect2TagWidget(HeavySelect2Mixin, Select2TagWidget):
 class ModelSelect2Mixin:
     """Widget mixin that provides attributes and methods for :class:`.AutoResponseView`."""
 
+    _word_split_pattern = re.compile(r"\t|\n| ")
+
     model = None
     queryset = None
     search_fields = []
@@ -397,14 +399,15 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
             queryset = self.get_queryset()
         search_fields = self.get_search_fields()
         select = Q()
-        term = term.replace("\t", " ")
-        term = term.replace("\n", " ")
-        for t in [t for t in term.split(" ") if not t == ""]:
-            select &= reduce(
-                lambda x, y: x | Q(**{y: t}),
-                search_fields[1:],
-                Q(**{search_fields[0]: t}),
-            )
+
+        for field in search_fields:
+            field_select = Q(**{field: term})
+            if "contains" in field:
+                for word in filter(None, self._word_split_pattern.split(term)):
+                    field_select |= Q(**{field: word})
+
+            select |= field_select
+
         if dependent_fields:
             select &= Q(**dependent_fields)
 
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 1f02c828..130f650c 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -446,6 +446,52 @@ def test_filter_queryset(self, genres):
         )
         assert qs.exists()
 
+    def test_filter_queryset__startswith(self, genres):
+        genre = Genre.objects.create(title="Space Genre")
+        widget = TitleModelSelect2Widget(queryset=Genre.objects.all())
+        assert widget.filter_queryset(None, genre.title).exists()
+
+        widget = TitleModelSelect2Widget(
+            search_fields=["title__istartswith"], queryset=Genre.objects.all()
+        )
+        qs = widget.filter_queryset(None, "Space Gen")
+        assert qs.exists()
+
+        qs = widget.filter_queryset(None, "Gen")
+        assert not qs.exists()
+
+    def test_filter_queryset__contains(self, genres):
+        genre = Genre.objects.create(title="Space Genre")
+        widget = TitleModelSelect2Widget(queryset=Genre.objects.all())
+        assert widget.filter_queryset(None, genre.title).exists()
+
+        widget = TitleModelSelect2Widget(
+            search_fields=["title__contains"], queryset=Genre.objects.all()
+        )
+        qs = widget.filter_queryset(None, "Space Gen")
+        assert qs.exists()
+
+        qs = widget.filter_queryset(None, "NOT Gen")
+        assert qs.exists(), "contains works even if only one part matches"
+
+    def test_filter_queryset__multiple_fields(self, genres):
+        genre = Genre.objects.create(title="Space Genre")
+        widget = TitleModelSelect2Widget(queryset=Genre.objects.all())
+        assert widget.filter_queryset(None, genre.title).exists()
+
+        widget = TitleModelSelect2Widget(
+            search_fields=[
+                "title__startswith",
+                "title__endswith",
+            ],
+            queryset=Genre.objects.all(),
+        )
+        qs = widget.filter_queryset(None, "Space")
+        assert qs.exists()
+
+        qs = widget.filter_queryset(None, "Genre")
+        assert qs.exists()
+
     def test_model_kwarg(self):
         widget = ModelSelect2Widget(model=Genre, search_fields=["title__icontains"])
         genre = Genre.objects.last()

From e735be2016f0a2349f0f8acd51eb6b51741cc123 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Sat, 16 Jan 2021 16:34:41 +0100
Subject: [PATCH 014/168] Fix #29 -- Do not filter based on empty search term

---
 django_select2/forms.py | 15 ++++++++-------
 tests/test_forms.py     | 10 ++++++++++
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 32d4ba11..76fc525a 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -400,13 +400,14 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
         search_fields = self.get_search_fields()
         select = Q()
 
-        for field in search_fields:
-            field_select = Q(**{field: term})
-            if "contains" in field:
-                for word in filter(None, self._word_split_pattern.split(term)):
-                    field_select |= Q(**{field: word})
-
-            select |= field_select
+        if term != "":
+            for field in search_fields:
+                field_select = Q(**{field: term})
+                if "contains" in field:
+                    for word in filter(None, self._word_split_pattern.split(term)):
+                        field_select |= Q(**{field: word})
+
+                select |= field_select
 
         if dependent_fields:
             select &= Q(**dependent_fields)
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 130f650c..85b9265a 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -446,6 +446,16 @@ def test_filter_queryset(self, genres):
         )
         assert qs.exists()
 
+    def test_filter_queryset__empty(self, genres):
+        widget = TitleModelSelect2Widget(queryset=Genre.objects.all())
+        assert widget.filter_queryset(None, genres[0].title[:3]).exists()
+
+        widget = TitleModelSelect2Widget(
+            search_fields=["title__icontains"], queryset=Genre.objects.all()
+        )
+        qs = widget.filter_queryset(None, "")
+        assert qs.exists()
+
     def test_filter_queryset__startswith(self, genres):
         genre = Genre.objects.create(title="Space Genre")
         widget = TitleModelSelect2Widget(queryset=Genre.objects.all())

From bc6282fa2f404d1557e9db7d5db6ea37c9cdb9ac Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Sat, 6 Mar 2021 11:38:46 +0100
Subject: [PATCH 015/168] Add dependabot config

---
 .github/dependabot.yml | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 .github/dependabot.yml

diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..3f541100
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,14 @@
+version: 2
+updates:
+- package-ecosystem: pip
+  directory: "/"
+  schedule:
+    interval: daily
+- package-ecosystem: npm
+  directory: "/"
+  schedule:
+    interval: daily
+- package-ecosystem: github-actions
+  directory: "/"
+  schedule:
+    interval: daily

From 44b2273396130466151a4972bbdb8de473fb5e96 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Sat, 6 Mar 2021 12:08:00 +0100
Subject: [PATCH 016/168] Switch to latest chromedriver version

---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bf69a668..6c2a9796 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -59,7 +59,7 @@ jobs:
       - name: Install Selenium
         run: |
           mkdir bin
-          curl -O https://chromedriver.storage.googleapis.com/77.0.3865.40/chromedriver_linux64.zip
+          curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
       - uses: actions/checkout@v1
       - name: Install dependencies

From fcea539712fbfe16444b5238d0f61c272dd8064b Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Sat, 6 Mar 2021 12:08:24 +0100
Subject: [PATCH 017/168] Resolve pytest deprecation warning

---
 tests/conftest.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/conftest.py b/tests/conftest.py
index e8d3455c..b5e37416 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -21,7 +21,7 @@ def random_name(n):
     return "-".join([x.capitalize() for x in words])
 
 
-@pytest.yield_fixture(scope="session")
+@pytest.fixture(scope="session")
 def driver():
     chrome_options = webdriver.ChromeOptions()
     chrome_options.headless = True

From c093aab18cde572272fa6217a482fc875099d17f Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sat, 6 Mar 2021 11:10:40 +0000
Subject: [PATCH 018/168] Bump actions/setup-node from v1 to v2.1.5

Bumps [actions/setup-node](https://github.com/actions/setup-node) from v1 to v2.1.5.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v1...46071b5c7a2e0c34e49c3cb8a0e792e86e18d5ea)

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 6c2a9796..944f2100 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2
-      - uses: actions/setup-node@v1
+      - uses: actions/setup-node@v2.1.5
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 699b3186..c3fefcfa 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v1
+      - uses: actions/setup-node@v2.1.5
       - uses: actions/setup-python@v1
       - uses: actions/checkout@v2
       - run: python set_version.py

From 05556e19527ddbb029f7307da469cadbf0c22c7a Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Sat, 6 Mar 2021 12:00:52 +0100
Subject: [PATCH 019/168] Resolve #39 -- Make default search more like Django
 admin

Different to before we now match search terms only if all
bits match or the entire statement. The last part differs
from the behavior in Django admin, which does not inlcude
exact machtes of the entire search term inlcude spaces.

Partially revert 07054b2d8ff15144c6b1b00577f3c898d47712bc
---
 django_select2/forms.py | 29 +++++++++++++++++------------
 tests/test_forms.py     |  2 +-
 2 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 76fc525a..2aac9e6a 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -46,12 +46,14 @@
     :parts: 1
 
 """
-import re
+import operator
 import uuid
+from functools import reduce
 from itertools import chain
 from pickle import PicklingError  # nosec
 
 from django import forms
+from django.contrib.admin.utils import lookup_needs_distinct
 from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
 from django.core import signing
 from django.db.models import Q
@@ -315,8 +317,6 @@ class HeavySelect2TagWidget(HeavySelect2Mixin, Select2TagWidget):
 class ModelSelect2Mixin:
     """Widget mixin that provides attributes and methods for :class:`.AutoResponseView`."""
 
-    _word_split_pattern = re.compile(r"\t|\n| ")
-
     model = None
     queryset = None
     search_fields = []
@@ -400,19 +400,24 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
         search_fields = self.get_search_fields()
         select = Q()
 
-        if term != "":
-            for field in search_fields:
-                field_select = Q(**{field: term})
-                if "contains" in field:
-                    for word in filter(None, self._word_split_pattern.split(term)):
-                        field_select |= Q(**{field: word})
-
-                select |= field_select
+        use_distinct = False
+        if search_fields and term:
+            for bit in term.split():
+                or_queries = [Q(**{orm_lookup: bit}) for orm_lookup in search_fields]
+                select &= reduce(operator.or_, or_queries)
+            or_queries = [Q(**{orm_lookup: term}) for orm_lookup in search_fields]
+            select |= reduce(operator.or_, or_queries)
+            use_distinct |= any(
+                lookup_needs_distinct(queryset.model._meta, search_spec)
+                for search_spec in search_fields
+            )
 
         if dependent_fields:
             select &= Q(**dependent_fields)
 
-        return queryset.filter(select).distinct()
+        if use_distinct:
+            queryset.filter(select).distinct()
+        return queryset.filter(select)
 
     def get_queryset(self):
         """
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 85b9265a..96fe3e6a 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -482,7 +482,7 @@ def test_filter_queryset__contains(self, genres):
         assert qs.exists()
 
         qs = widget.filter_queryset(None, "NOT Gen")
-        assert qs.exists(), "contains works even if only one part matches"
+        assert not qs.exists(), "contains works even if all bits match"
 
     def test_filter_queryset__multiple_fields(self, genres):
         genre = Genre.objects.create(title="Space Genre")

From dc91f0305ef979957983fe2a6c09a38af640addf Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Mon, 29 Mar 2021 17:35:56 +0200
Subject: [PATCH 020/168] Add support for dependent m2m fields

---
 django_select2/views.py | 15 ++++++++++++---
 tests/test_forms.py     |  2 +-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/django_select2/views.py b/django_select2/views.py
index ec541d11..6295c519 100644
--- a/django_select2/views.py
+++ b/django_select2/views.py
@@ -51,11 +51,20 @@ def get_queryset(self):
         kwargs = {
             model_field_name: self.request.GET.get(form_field_name)
             for form_field_name, model_field_name in self.widget.dependent_fields.items()
-            if form_field_name in self.request.GET
-            and self.request.GET.get(form_field_name, "") != ""
         }
+        kwargs.update(
+            {
+                f"{model_field_name}__in": filter(
+                    None, self.request.GET.get(f"{form_field_name}[]", "").split(",")
+                )
+                for form_field_name, model_field_name in self.widget.dependent_fields.items()
+            }
+        )
         return self.widget.filter_queryset(
-            self.request, self.term, self.queryset, **kwargs
+            self.request,
+            self.term,
+            self.queryset,
+            **{k: v for k, v in kwargs.items() if v},
         )
 
     def get_paginate_by(self, queryset):
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 96fe3e6a..9487e428 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -200,7 +200,7 @@ def test_empty_css_setting(self, settings):
         settings.SELECT2_CSS = ""
         sut = Select2Widget()
         result = sut.media.render()
-        assert ".css" not in result
+        assert "/select2.css" not in result
 
 
 class TestHeavySelect2Mixin(TestSelect2Mixin):

From b1b229f5464a746132f26ba44114c619e2ec9c47 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Mon, 29 Mar 2021 17:43:24 +0200
Subject: [PATCH 021/168] Add css support for Django admin

---
 MANIFEST.in                                             | 1 +
 django_select2/forms.py                                 | 2 +-
 django_select2/static/django_select2/django_select2.css | 3 +++
 3 files changed, 5 insertions(+), 1 deletion(-)
 create mode 100644 django_select2/static/django_select2/django_select2.css

diff --git a/MANIFEST.in b/MANIFEST.in
index 33ef41f2..d6400132 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,5 @@
 include django_select2/static/django_select2/django_select2.js
+include django_select2/static/django_select2/django_select2.css
 prune tests
 prune .github
 exclude .fussyfox.yml
diff --git a/django_select2/forms.py b/django_select2/forms.py
index 2aac9e6a..0cccb132 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -121,7 +121,7 @@ def _get_media(self):
 
         return forms.Media(
             js=select2_js + i18n_file + ("django_select2/django_select2.js",),
-            css={"screen": select2_css},
+            css={"screen": select2_css + ("django_select2/django_select2.css",)},
         )
 
     media = property(_get_media)
diff --git a/django_select2/static/django_select2/django_select2.css b/django_select2/static/django_select2/django_select2.css
new file mode 100644
index 00000000..09a93207
--- /dev/null
+++ b/django_select2/static/django_select2/django_select2.css
@@ -0,0 +1,3 @@
+.change-form select.django-select2 {
+  width: 20em;
+}

From 13d6a40796a5bf4d9006fbf1696c2ede0540e786 Mon Sep 17 00:00:00 2001
From: Cleiton Lima <cleiton.limapin@gmail.com>
Date: Wed, 31 Mar 2021 19:06:05 -0300
Subject: [PATCH 022/168] Added *.egg-info in .gitignore

---
 .gitignore | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index 875d21f9..d1ef58f6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
 *.pyc
 
-Django_Select2.egg-info
-Django_Select2_Py3.egg-info
+*.egg-info
 dist
 build
 

From 62d85d57dabe595199201104c57c14ea9be95d78 Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 13 Apr 2021 17:26:38 +0200
Subject: [PATCH 023/168] Fix #52 -- Get all dependent field values

---
 django_select2/views.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/django_select2/views.py b/django_select2/views.py
index 6295c519..c03f683e 100644
--- a/django_select2/views.py
+++ b/django_select2/views.py
@@ -54,8 +54,8 @@ def get_queryset(self):
         }
         kwargs.update(
             {
-                f"{model_field_name}__in": filter(
-                    None, self.request.GET.get(f"{form_field_name}[]", "").split(",")
+                f"{model_field_name}__in": self.request.GET.getlist(
+                    f"{form_field_name}[]", []
                 )
                 for form_field_name, model_field_name in self.widget.dependent_fields.items()
             }

From 3448ce758b95ec4ce77187418a7e2a11f3fb214b Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 13 Apr 2021 17:27:17 +0200
Subject: [PATCH 024/168] Fix distinct results

---
 django_select2/forms.py | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 0cccb132..2a88c215 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -415,8 +415,13 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
         if dependent_fields:
             select &= Q(**dependent_fields)
 
+        use_distinct |= any(
+            lookup_needs_distinct(queryset.model._meta, search_spec)
+            for search_spec in dependent_fields.keys()
+        )
+
         if use_distinct:
-            queryset.filter(select).distinct()
+            return queryset.filter(select).distinct()
         return queryset.filter(select)
 
     def get_queryset(self):

From 038026c2f96d41810de567a7c159655c30bee46f Mon Sep 17 00:00:00 2001
From: Johannes Maron <info@johanneshoppe.com>
Date: Tue, 13 Apr 2021 17:51:17 +0200
Subject: [PATCH 025/168] Add Django 3.2 to CI suite

---
 .github/workflows/ci.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 944f2100..3ac48048 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -48,6 +48,7 @@ jobs:
         django-version:
           - "2.2"
           - "3.1"
+          - "3.2"
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}

From fcd825dca416cea440d23e3dd68ec184447c50dd Mon Sep 17 00:00:00 2001
From: Arne Bertrand <arnebertrand@gmail.com>
Date: Mon, 19 Apr 2021 17:48:35 +0200
Subject: [PATCH 026/168] Clarify that cache is not strictly necessary (#16)

---
 docs/index.rst | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/docs/index.rst b/docs/index.rst
index 6f8b0d26..0ae73cbd 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -21,9 +21,21 @@ Add ``django_select`` to your URL root configuration:
         # … other patterns
     ]
 
-Finally make sure you have a persistent cache backend setup (NOT
-:class:`.DummyCache` or :class:`.LocMemCache`), we will use Redis in this
-example. Make sure you have a Redis server up and running::
+
+``django-select2`` requires a cache backend which is **persistent**
+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 
+you scale up into multiple servers.
+
+Below is an example setup using Redis, which is a solution that
+works for multi-server setups:
+
+Make sure you have a Redis server up and running::
 
     # Debian
     sudo apt-get install redis-server

From c049b30b0858ebe819f88e3167be41a2edc4ccc1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 12 May 2021 06:03:55 +0000
Subject: [PATCH 027/168] Bump actions/checkout from 2 to 2.3.4

Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 2.3.4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2...v2.3.4)

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 8 ++++----
 .github/workflows/release.yml | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3ac48048..5d8a0ff2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,14 +12,14 @@ jobs:
     steps:
       - uses: actions/setup-python@v2
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v2.3.4
       - run: python setup.py sdist bdist_wheel
       - run: python -m twine check dist/*
 
   standardjs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v2.3.4
       - uses: actions/setup-node@v2.1.5
         with:
           node-version: '12.x'
@@ -31,7 +31,7 @@ jobs:
     steps:
       - uses: actions/setup-python@v2
       - run: python -m pip install -U setuptools wheel
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v2.3.4
       - run: sudo apt-get install -y gettext graphviz
       - run: python setup.py develop
       - run: python setup.py build_sphinx -W -b doctest -b html
@@ -62,7 +62,7 @@ jobs:
           mkdir bin
           curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
-      - uses: actions/checkout@v1
+      - uses: actions/checkout@v2.3.4
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip setuptools wheel codecov
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c3fefcfa..fe339400 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-python@v2
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v2.3.4
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
       - name: Build dist packages
@@ -25,7 +25,7 @@ jobs:
     steps:
       - uses: actions/setup-node@v2.1.5
       - uses: actions/setup-python@v1
-      - uses: actions/checkout@v2
+      - uses: actions/checkout@v2.3.4
       - run: python set_version.py
       - name: Upload packages
         run: npm publish

From c1900dd737f29e853c561b64ac9edf45ada1e846 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 12 May 2021 07:42:28 +0000
Subject: [PATCH 028/168] Bump actions/setup-python from 2 to 2.2.2

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 2.2.2.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...v2.2.2)

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 6 +++---
 .github/workflows/release.yml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5d8a0ff2..28bcb854 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2
+      - uses: actions/setup-python@v2.2.2
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - uses: actions/checkout@v2.3.4
       - run: python setup.py sdist bdist_wheel
@@ -29,7 +29,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2
+      - uses: actions/setup-python@v2.2.2
       - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v2.3.4
       - run: sudo apt-get install -y gettext graphviz
@@ -52,7 +52,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v2
+        uses: actions/setup-python@v2.2.2
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Chrome
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fe339400..ba9ca0f5 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2
+      - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v2.1.5
-      - uses: actions/setup-python@v1
+      - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py
       - name: Upload packages

From 4ff262f707e827d0ea2ce4431ec5f0f6eba0fee0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 1 Jul 2021 05:05:49 +0000
Subject: [PATCH 029/168] Bump actions/setup-node from 2.1.5 to 2.2.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.1.5 to 2.2.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.1.5...v2.2.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 28bcb854..5998b271 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.1.5
+      - uses: actions/setup-node@v2.2.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index ba9ca0f5..4e23f082 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.1.5
+      - uses: actions/setup-node@v2.2.0
       - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py

From 4d51978cb93e5d07cc3d686911e9b0c5b6618758 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 21 Jul 2021 05:05:57 +0000
Subject: [PATCH 030/168] Bump actions/setup-node from 2.2.0 to 2.3.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.2.0 to 2.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5998b271..f7aca8c0 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.2.0
+      - uses: actions/setup-node@v2.3.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4e23f082..675a0160 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.2.0
+      - uses: actions/setup-node@v2.3.0
       - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py

From 09dbceb6ba1f92fcb6747afdb61ad500d4e56cde Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 4 Aug 2021 05:06:29 +0000
Subject: [PATCH 031/168] Bump actions/setup-node from 2.3.0 to 2.3.1

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.3.0...v2.3.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f7aca8c0..4e134a53 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.3.0
+      - uses: actions/setup-node@v2.3.1
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 675a0160..a6a467d9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.3.0
+      - uses: actions/setup-node@v2.3.1
       - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py

From d6e1ab3d61caac79a259732aedbd667cbf910915 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 5 Aug 2021 05:06:58 +0000
Subject: [PATCH 032/168] Bump actions/setup-node from 2.3.1 to 2.3.2

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.3.1...v2.3.2)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4e134a53..94df296b 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.3.1
+      - uses: actions/setup-node@v2.3.2
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a6a467d9..fb5901a9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.3.1
+      - uses: actions/setup-node@v2.3.2
       - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py

From bfc9313af4a738ca22580dc124916f9c4b0a4c5e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 6 Aug 2021 05:08:45 +0000
Subject: [PATCH 033/168] Bump actions/setup-node from 2.3.2 to 2.4.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.3.2 to 2.4.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.3.2...v2.4.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 94df296b..b246a9d8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.3.2
+      - uses: actions/setup-node@v2.4.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fb5901a9..4e964edb 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.3.2
+      - uses: actions/setup-node@v2.4.0
       - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py

From 1125ced364b2d716bd8e22389d6938ca4c330f11 Mon Sep 17 00:00:00 2001
From: Cleiton Lima <cleiton.limapin@gmail.com>
Date: Tue, 21 Sep 2021 12:27:15 -0300
Subject: [PATCH 034/168] Added lang attribute to widgets

---
 django_select2/forms.py | 33 ++++++++++++++++-----------------
 tests/test_forms.py     | 13 +++++++++++++
 2 files changed, 29 insertions(+), 17 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 2a88c215..98079386 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -76,9 +76,16 @@ class Select2Mixin:
 
     empty_label = ""
 
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+        self.i18n_name = SELECT2_TRANSLATIONS.get(get_language())
+
     def build_attrs(self, base_attrs, extra_attrs=None):
         """Add select2 data attributes."""
-        default_attrs = {"data-minimum-input-length": 0}
+        default_attrs = {
+            "lang": self.i18n_name,
+            "data-minimum-input-length": 0,
+        }
         if self.is_required:
             default_attrs["data-allow-clear"] = "false"
         else:
@@ -100,32 +107,28 @@ def optgroups(self, name, value, attrs=None):
             self.choices = list(chain([("", "")], self.choices))
         return super().optgroups(name, value, attrs=attrs)
 
-    def _get_media(self):
+    @property
+    def media(self):
         """
         Construct Media as a dynamic property.
 
         .. Note:: For more information visit
             https://docs.djangoproject.com/en/stable/topics/forms/media/#media-as-a-dynamic-property
         """
-        lang = get_language()
         select2_js = (settings.SELECT2_JS,) if settings.SELECT2_JS else ()
         select2_css = (settings.SELECT2_CSS,) if settings.SELECT2_CSS else ()
 
-        i18n_name = SELECT2_TRANSLATIONS.get(lang)
-        if i18n_name not in settings.SELECT2_I18N_AVAILABLE_LANGUAGES:
-            i18n_name = None
-
-        i18n_file = (
-            ("%s/%s.js" % (settings.SELECT2_I18N_PATH, i18n_name),) if i18n_name else ()
-        )
+        i18n_file = ()
+        if self.i18n_name in settings.SELECT2_I18N_AVAILABLE_LANGUAGES:
+            i18n_file = (
+                ("%s/%s.js" % (settings.SELECT2_I18N_PATH, self.i18n_name),)
+            )
 
         return forms.Media(
             js=select2_js + i18n_file + ("django_select2/django_select2.js",),
             css={"screen": select2_css + ("django_select2/django_select2.css",)},
         )
 
-    media = property(_get_media)
-
 
 class Select2TagMixin:
     """Mixin to add select2 tag functionality."""
@@ -212,11 +215,7 @@ def __init__(self, attrs=None, choices=(), **kwargs):
                 Value is a name of a field in a model (used in `queryset`).
 
         """
-        self.choices = choices
-        if attrs is not None:
-            self.attrs = attrs.copy()
-        else:
-            self.attrs = {}
+        super().__init__(attrs, choices)
 
         self.uuid = str(uuid.uuid4())
         self.field_id = signing.dumps(self.uuid)
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 9487e428..af988845 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -3,6 +3,7 @@
 from collections.abc import Iterable
 
 import pytest
+from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
 from django.db.models import QuerySet
 from django.urls import reverse
 from django.utils import translation
@@ -46,6 +47,12 @@ def test_initial_form_class(self):
         assert "my-class" in widget.render("name", None)
         assert "django-select2" in widget.render("name", None)
 
+    @pytest.mark.parametrize("code,name", SELECT2_TRANSLATIONS.items())
+    def test_lang_attr(self, code, name):
+        translation.activate(code)
+        widget = self.widget_cls()
+        assert f'lang="{name}"' in widget.render("name", None)
+
     def test_allow_clear(self, db):
         required_field = self.form.fields["artist"]
         assert required_field.required is True
@@ -219,6 +226,12 @@ def test_initial_form_class(self):
             "name", None
         )
 
+    @pytest.mark.parametrize("code,name", SELECT2_TRANSLATIONS.items())
+    def test_lang_attr(self, code, name):
+        translation.activate(code)
+        widget = self.widget_cls(data_view="heavy_data_1")
+        assert f'lang="{name}"' in widget.render("name", None)
+
     def test_selected_option(self, db):
         not_required_field = self.form.fields["primary_genre"]
         assert not_required_field.required is False

From 820f2cb32c5ba67c15d03b5a59fb4956d5a11a0a Mon Sep 17 00:00:00 2001
From: Cleiton Lima <cleiton.limapin@gmail.com>
Date: Tue, 21 Sep 2021 12:32:53 -0300
Subject: [PATCH 035/168] Added LANGUAGE_CODE for tests

---
 tests/testapp/settings.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py
index b5ded121..f46d128d 100644
--- a/tests/testapp/settings.py
+++ b/tests/testapp/settings.py
@@ -25,6 +25,7 @@
     ("de", "German"),
     ("en", "English"),
 ]
+LANGUAGE_CODE = "en"
 
 TEMPLATES = [
     {

From 742d92927405f6a33449c4b615863fa6dc2dc0b0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 28 Sep 2021 05:08:36 +0000
Subject: [PATCH 036/168] Bump actions/setup-node from 2.4.0 to 2.4.1

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.4.0 to 2.4.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.4.0...v2.4.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b246a9d8..ffd86bcc 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.3.4
-      - uses: actions/setup-node@v2.4.0
+      - uses: actions/setup-node@v2.4.1
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 4e964edb..e921a106 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.4.0
+      - uses: actions/setup-node@v2.4.1
       - uses: actions/setup-python@v2.2.2
       - uses: actions/checkout@v2.3.4
       - run: python set_version.py

From f94e17678a16112ed64d536e4325e3c6f3870b43 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 2 Oct 2021 13:59:21 +0200
Subject: [PATCH 037/168] Resolve #92 -- Add tests to sdist package

---
 MANIFEST.in | 1 -
 1 file changed, 1 deletion(-)

diff --git a/MANIFEST.in b/MANIFEST.in
index d6400132..28040cc0 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,5 @@
 include django_select2/static/django_select2/django_select2.js
 include django_select2/static/django_select2/django_select2.css
-prune tests
 prune .github
 exclude .fussyfox.yml
 exclude .travis.yml

From 581e2d15f516a6926a90915ff2861da19c184874 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 2 Oct 2021 14:10:31 +0200
Subject: [PATCH 038/168] Remove other unneeded files

---
 MANIFEST.in | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/MANIFEST.in b/MANIFEST.in
index 28040cc0..45907113 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,6 +1,5 @@
 include django_select2/static/django_select2/django_select2.js
 include django_select2/static/django_select2/django_select2.css
 prune .github
-exclude .fussyfox.yml
-exclude .travis.yml
-exclude .gitignore
+exclude .*
+

From 36f9ac06947b7a271cdc2eec64169abb06755dc9 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 2 Oct 2021 14:50:57 +0200
Subject: [PATCH 039/168] Add Django 4.0 compatibility

---
 django_select2/forms.py | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 98079386..86ca0390 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -52,8 +52,8 @@
 from itertools import chain
 from pickle import PicklingError  # nosec
 
+import django
 from django import forms
-from django.contrib.admin.utils import lookup_needs_distinct
 from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
 from django.core import signing
 from django.db.models import Q
@@ -64,6 +64,11 @@
 from .cache import cache
 from .conf import settings
 
+if django.VERSION < (4, 0):
+    from django.contrib.admin.utils import lookup_needs_distinct as lookup_spawns_duplicates
+else:
+    from django.contrib.admin.utils import lookup_spawns_duplicates
+
 
 class Select2Mixin:
     """
@@ -407,7 +412,7 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
             or_queries = [Q(**{orm_lookup: term}) for orm_lookup in search_fields]
             select |= reduce(operator.or_, or_queries)
             use_distinct |= any(
-                lookup_needs_distinct(queryset.model._meta, search_spec)
+                lookup_spawns_duplicates(queryset.model._meta, search_spec)
                 for search_spec in search_fields
             )
 
@@ -415,7 +420,7 @@ def filter_queryset(self, request, term, queryset=None, **dependent_fields):
             select &= Q(**dependent_fields)
 
         use_distinct |= any(
-            lookup_needs_distinct(queryset.model._meta, search_spec)
+            lookup_spawns_duplicates(queryset.model._meta, search_spec)
             for search_spec in dependent_fields.keys()
         )
 

From e15ced997d376f986f4cb6c77eb70846733d7265 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 2 Oct 2021 14:53:18 +0200
Subject: [PATCH 040/168] Update version makers and Ci suite

---
 .github/workflows/ci.yml | 9 ++++++---
 setup.cfg                | 4 +++-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ffd86bcc..aa472d42 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -46,9 +46,12 @@ jobs:
           - "3.8"
           - "3.9"
         django-version:
-          - "2.2"
-          - "3.1"
-          - "3.2"
+          - "2.2.0"
+          - "3.2.0"
+          - "4.0a1"
+        exclude:
+          - python-version: "3.7"
+            django-version: "4.0a1"
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
diff --git a/setup.cfg b/setup.cfg
index 98161532..317db187 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -19,9 +19,11 @@ classifier =
     Programming Language :: Python :: 3.6
     Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
+    Programming Language :: Python :: 3.9
     Framework :: Django
     Framework :: Django :: 2.2
-    Framework :: Django :: 3.0
+    Framework :: Django :: 3.1
+    Framework :: Django :: 4.0
 
 [options]
 include_package_data = True

From 1063fba8b34d858ddac2403ba22e8d36f24dc2be Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 18 Oct 2021 05:09:43 +0000
Subject: [PATCH 041/168] Bump actions/checkout from 2.3.4 to 2.3.5

Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.4 to 2.3.5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2.3.4...v2.3.5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 8 ++++----
 .github/workflows/release.yml | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index aa472d42..1bd7e65a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,14 +12,14 @@ jobs:
     steps:
       - uses: actions/setup-python@v2.2.2
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
-      - uses: actions/checkout@v2.3.4
+      - uses: actions/checkout@v2.3.5
       - run: python setup.py sdist bdist_wheel
       - run: python -m twine check dist/*
 
   standardjs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2.3.4
+      - uses: actions/checkout@v2.3.5
       - uses: actions/setup-node@v2.4.1
         with:
           node-version: '12.x'
@@ -31,7 +31,7 @@ jobs:
     steps:
       - uses: actions/setup-python@v2.2.2
       - run: python -m pip install -U setuptools wheel
-      - uses: actions/checkout@v2.3.4
+      - uses: actions/checkout@v2.3.5
       - run: sudo apt-get install -y gettext graphviz
       - run: python setup.py develop
       - run: python setup.py build_sphinx -W -b doctest -b html
@@ -65,7 +65,7 @@ jobs:
           mkdir bin
           curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
-      - uses: actions/checkout@v2.3.4
+      - uses: actions/checkout@v2.3.5
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip setuptools wheel codecov
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e921a106..f014b665 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-python@v2.2.2
-      - uses: actions/checkout@v2.3.4
+      - uses: actions/checkout@v2.3.5
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
       - name: Build dist packages
@@ -25,7 +25,7 @@ jobs:
     steps:
       - uses: actions/setup-node@v2.4.1
       - uses: actions/setup-python@v2.2.2
-      - uses: actions/checkout@v2.3.4
+      - uses: actions/checkout@v2.3.5
       - run: python set_version.py
       - name: Upload packages
         run: npm publish

From 5a835f37f4eb70ce8ef12b6682c252a61f3b9577 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Mon, 18 Oct 2021 15:45:21 +0200
Subject: [PATCH 042/168] Resolve #91 -- Add comment about cache expiration

---
 docs/index.rst | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/docs/index.rst b/docs/index.rst
index 0ae73cbd..6ba1f8f3 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -64,6 +64,12 @@ Next, add the cache configuration to your ``settings.py`` as follows:
     # Tell select2 which cache configuration to use:
     SELECT2_CACHE_BACKEND = "select2"
 
+.. note::
+    A custom timeout for your cache backend, will serve as an indirect session limit.
+    Auto select fields will stop working after, once the cache has expired.
+    It's recommended to use a dedicated cache database with an adequate
+    cache replacement policy such as LRU, FILO, etc.
+
 
 External Dependencies
 ---------------------

From 6bd7fb5f1edfbf5635fac0a0db1a7c6814bae137 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 3 Nov 2021 05:06:19 +0000
Subject: [PATCH 043/168] Bump actions/checkout from 2.3.5 to 2.4.0

Bumps [actions/checkout](https://github.com/actions/checkout) from 2.3.5 to 2.4.0.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2.3.5...v2.4.0)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 8 ++++----
 .github/workflows/release.yml | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1bd7e65a..ea6cb0e2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,14 +12,14 @@ jobs:
     steps:
       - uses: actions/setup-python@v2.2.2
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
-      - uses: actions/checkout@v2.3.5
+      - uses: actions/checkout@v2.4.0
       - run: python setup.py sdist bdist_wheel
       - run: python -m twine check dist/*
 
   standardjs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2.3.5
+      - uses: actions/checkout@v2.4.0
       - uses: actions/setup-node@v2.4.1
         with:
           node-version: '12.x'
@@ -31,7 +31,7 @@ jobs:
     steps:
       - uses: actions/setup-python@v2.2.2
       - run: python -m pip install -U setuptools wheel
-      - uses: actions/checkout@v2.3.5
+      - uses: actions/checkout@v2.4.0
       - run: sudo apt-get install -y gettext graphviz
       - run: python setup.py develop
       - run: python setup.py build_sphinx -W -b doctest -b html
@@ -65,7 +65,7 @@ jobs:
           mkdir bin
           curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
-      - uses: actions/checkout@v2.3.5
+      - uses: actions/checkout@v2.4.0
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip setuptools wheel codecov
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f014b665..3deeaffc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-python@v2.2.2
-      - uses: actions/checkout@v2.3.5
+      - uses: actions/checkout@v2.4.0
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
       - name: Build dist packages
@@ -25,7 +25,7 @@ jobs:
     steps:
       - uses: actions/setup-node@v2.4.1
       - uses: actions/setup-python@v2.2.2
-      - uses: actions/checkout@v2.3.5
+      - uses: actions/checkout@v2.4.0
       - run: python set_version.py
       - name: Upload packages
         run: npm publish

From 5f0d76de317f17b883446ca008986ba6d2927a7a Mon Sep 17 00:00:00 2001
From: Greg Kaleka <greg@gregkaleka.com>
Date: Thu, 28 Oct 2021 16:54:41 -0700
Subject: [PATCH 044/168] Don't set default_app_config in Django 3.2 up

As of Django 3.2, explicitly setting `default_app_config` [is deprecated](https://docs.djangoproject.com/en/3.2/releases/3.2/#features-deprecated-in-3-2). This check allows django-select2 to continue supporting earlier versions of Django while silencing this deprecation warning.
---
 django_select2/__init__.py | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/django_select2/__init__.py b/django_select2/__init__.py
index 546ae234..d2d415b3 100644
--- a/django_select2/__init__.py
+++ b/django_select2/__init__.py
@@ -7,4 +7,7 @@
 .. _Select2: https://select2.org/
 
 """
-default_app_config = "django_select2.apps.Select2AppConfig"
+from django import get_version
+
+if get_version() < '3.2':
+    default_app_config = "django_select2.apps.Select2AppConfig"

From 3ef5fd164d93cc464cb564e0f9e5fe6d02951d5b Mon Sep 17 00:00:00 2001
From: Cleiton Lima <cleiton.limapin@gmail.com>
Date: Tue, 2 Nov 2021 22:47:53 -0300
Subject: [PATCH 045/168] Added SELECT2_THEME settings

---
 django_select2/conf.py  | 16 ++++++++++++++++
 django_select2/forms.py | 18 ++++++++++--------
 tests/test_forms.py     | 17 +++++++++++++++++
 3 files changed, 43 insertions(+), 8 deletions(-)

diff --git a/django_select2/conf.py b/django_select2/conf.py
index 4d686005..8862932a 100644
--- a/django_select2/conf.py
+++ b/django_select2/conf.py
@@ -87,6 +87,14 @@ class Select2Conf(AppConf):
 
         SELECT2_CSS = 'assets/css/select2.css'
 
+    If you want to add more css (usually used in select2 themes), add a line
+    in settings.py like this::
+
+        SELECT2_CSS = [
+            'assets/css/select2.css',
+            'assets/css/select2-theme.css',
+        ]
+
     If you provide your own CSS and would not like Django-Select2 to load any, change
     this setting to a blank string like so::
 
@@ -96,6 +104,14 @@ class Select2Conf(AppConf):
         develop without an Internet connection.
     """
 
+    THEME = "default"
+    """
+    Select2 supports custom themes using the theme option so you can style Select2
+    to match the rest of your application.
+
+    .. 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
diff --git a/django_select2/forms.py b/django_select2/forms.py
index 86ca0390..b40b6207 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -90,6 +90,7 @@ def build_attrs(self, base_attrs, extra_attrs=None):
         default_attrs = {
             "lang": self.i18n_name,
             "data-minimum-input-length": 0,
+            "data-theme": settings.SELECT2_THEME,
         }
         if self.is_required:
             default_attrs["data-allow-clear"] = "false"
@@ -120,18 +121,19 @@ def media(self):
         .. Note:: For more information visit
             https://docs.djangoproject.com/en/stable/topics/forms/media/#media-as-a-dynamic-property
         """
-        select2_js = (settings.SELECT2_JS,) if settings.SELECT2_JS else ()
-        select2_css = (settings.SELECT2_CSS,) if settings.SELECT2_CSS else ()
+        select2_js = [settings.SELECT2_JS] if settings.SELECT2_JS else []
+        select2_css = settings.SELECT2_CSS if settings.SELECT2_CSS else []
 
-        i18n_file = ()
+        if isinstance(select2_css, str):
+            select2_css = [select2_css]
+
+        i18n_file = []
         if self.i18n_name in settings.SELECT2_I18N_AVAILABLE_LANGUAGES:
-            i18n_file = (
-                ("%s/%s.js" % (settings.SELECT2_I18N_PATH, self.i18n_name),)
-            )
+            i18n_file = [f"{settings.SELECT2_I18N_PATH}/{self.i18n_name}.js"]
 
         return forms.Media(
-            js=select2_js + i18n_file + ("django_select2/django_select2.js",),
-            css={"screen": select2_css + ("django_select2/django_select2.css",)},
+            js=select2_js + i18n_file + ["django_select2/django_select2.js"],
+            css={"screen": select2_css + ["django_select2/django_select2.css"]},
         )
 
 
diff --git a/tests/test_forms.py b/tests/test_forms.py
index af988845..5a89dfd1 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -169,6 +169,11 @@ def test_i18n(self):
             "django_select2/django_select2.js",
         )
 
+    def test_theme_setting(self, settings):
+        settings.SELECT2_THEME = "classic"
+        widget = self.widget_cls()
+        assert 'data-theme="classic"' in widget.render("name", None)
+
 
 class TestSelect2MixinSettings:
     def test_default_media(self):
@@ -209,6 +214,13 @@ def test_empty_css_setting(self, settings):
         result = sut.media.render()
         assert "/select2.css" not in result
 
+    def test_multiple_css_setting(self, settings):
+        settings.SELECT2_CSS = ["select2.css", "select2-theme.css"]
+        sut = Select2Widget()
+        result = sut.media.render()
+        assert "select2.css" in result
+        assert "select2-theme.css" in result
+
 
 class TestHeavySelect2Mixin(TestSelect2Mixin):
     url = reverse("heavy_select2_widget")
@@ -321,6 +333,11 @@ class NoPickle:
         with pytest.raises(NotImplementedError):
             widget.set_to_cache()
 
+    def test_theme_setting(self, settings):
+        settings.SELECT2_THEME = "classic"
+        widget = self.widget_cls(data_view="heavy_data_1")
+        assert 'data-theme="classic"' in widget.render("name", None)
+
 
 class TestModelSelect2Mixin(TestHeavySelect2Mixin):
     form = forms.AlbumModelSelect2WidgetForm(initial={"primary_genre": 1})

From 8d74d47a9affe51639a8efb1cf5f786be8275720 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 18 Nov 2021 05:05:44 +0000
Subject: [PATCH 046/168] Bump actions/setup-python from 2.2.2 to 2.3.0

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.2.2 to 2.3.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2.2.2...v2.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 6 +++---
 .github/workflows/release.yml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ea6cb0e2..ad19eb79 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.2.2
+      - uses: actions/setup-python@v2.3.0
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - uses: actions/checkout@v2.4.0
       - run: python setup.py sdist bdist_wheel
@@ -29,7 +29,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.2.2
+      - uses: actions/setup-python@v2.3.0
       - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v2.4.0
       - run: sudo apt-get install -y gettext graphviz
@@ -55,7 +55,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v2.2.2
+        uses: actions/setup-python@v2.3.0
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Chrome
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3deeaffc..1ce1e7ff 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.2.2
+      - uses: actions/setup-python@v2.3.0
       - uses: actions/checkout@v2.4.0
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v2.4.1
-      - uses: actions/setup-python@v2.2.2
+      - uses: actions/setup-python@v2.3.0
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py
       - name: Upload packages

From e88bfc266a7f5a997f0a9921aaeec86930fde03c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 30 Nov 2021 05:08:21 +0000
Subject: [PATCH 047/168] Bump actions/setup-node from 2.4.1 to 2.5.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.4.1 to 2.5.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.4.1...v2.5.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ad19eb79..74964894 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.4.0
-      - uses: actions/setup-node@v2.4.1
+      - uses: actions/setup-node@v2.5.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 1ce1e7ff..f2f381b8 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.4.1
+      - uses: actions/setup-node@v2.5.0
       - uses: actions/setup-python@v2.3.0
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py

From 153dda64ee9a8946ac32999a148877a5ac481407 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 30 Nov 2021 08:47:12 +0000
Subject: [PATCH 048/168] Bump actions/setup-python from 2.3.0 to 2.3.1

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.0 to 2.3.1.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2.3.0...v2.3.1)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 6 +++---
 .github/workflows/release.yml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 74964894..7e30a0c1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.0
+      - uses: actions/setup-python@v2.3.1
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - uses: actions/checkout@v2.4.0
       - run: python setup.py sdist bdist_wheel
@@ -29,7 +29,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.0
+      - uses: actions/setup-python@v2.3.1
       - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v2.4.0
       - run: sudo apt-get install -y gettext graphviz
@@ -55,7 +55,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v2.3.0
+        uses: actions/setup-python@v2.3.1
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Chrome
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f2f381b8..9d06a17e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.0
+      - uses: actions/setup-python@v2.3.1
       - uses: actions/checkout@v2.4.0
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v2.5.0
-      - uses: actions/setup-python@v2.3.0
+      - uses: actions/setup-python@v2.3.1
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py
       - name: Upload packages

From b85895363f4f82d5f8774fdeb4eb6a1f59f26364 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 29 Dec 2021 05:07:52 +0000
Subject: [PATCH 049/168] Bump actions/setup-node from 2.5.0 to 2.5.1

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.5.0 to 2.5.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.5.0...v2.5.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7e30a0c1..2feb4772 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.4.0
-      - uses: actions/setup-node@v2.5.0
+      - uses: actions/setup-node@v2.5.1
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 9d06a17e..047b387c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.5.0
+      - uses: actions/setup-node@v2.5.1
       - uses: actions/setup-python@v2.3.1
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py

From 6e7e45816a12f5a36feb71e23845141d68e35e34 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Thu, 3 Feb 2022 20:09:04 +0100
Subject: [PATCH 050/168] Add Select2 mixin that uses Django's own select
 template

---
 django_select2/__init__.py |  2 +-
 django_select2/forms.py    | 29 ++++++++++++++++++++++++-----
 tests/test_forms.py        | 18 ++++++++++++++++++
 3 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/django_select2/__init__.py b/django_select2/__init__.py
index d2d415b3..575a0213 100644
--- a/django_select2/__init__.py
+++ b/django_select2/__init__.py
@@ -9,5 +9,5 @@
 """
 from django import get_version
 
-if get_version() < '3.2':
+if get_version() < "3.2":
     default_app_config = "django_select2.apps.Select2AppConfig"
diff --git a/django_select2/forms.py b/django_select2/forms.py
index b40b6207..df3982fe 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -54,7 +54,7 @@
 
 import django
 from django import forms
-from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
+from django.contrib.admin.widgets import SELECT2_TRANSLATIONS, AutocompleteMixin
 from django.core import signing
 from django.db.models import Q
 from django.forms.models import ModelChoiceIterator
@@ -65,7 +65,9 @@
 from .conf import settings
 
 if django.VERSION < (4, 0):
-    from django.contrib.admin.utils import lookup_needs_distinct as lookup_spawns_duplicates
+    from django.contrib.admin.utils import (
+        lookup_needs_distinct as lookup_spawns_duplicates,
+    )
 else:
     from django.contrib.admin.utils import lookup_spawns_duplicates
 
@@ -79,6 +81,9 @@ class Select2Mixin:
     form media.
     """
 
+    css_class_name = "django-select2"
+    theme = None
+
     empty_label = ""
 
     def __init__(self, *args, **kwargs):
@@ -90,7 +95,7 @@ def build_attrs(self, base_attrs, extra_attrs=None):
         default_attrs = {
             "lang": self.i18n_name,
             "data-minimum-input-length": 0,
-            "data-theme": settings.SELECT2_THEME,
+            "data-theme": self.theme or settings.SELECT2_THEME,
         }
         if self.is_required:
             default_attrs["data-allow-clear"] = "false"
@@ -102,9 +107,9 @@ def build_attrs(self, base_attrs, extra_attrs=None):
         attrs = super().build_attrs(default_attrs, extra_attrs=extra_attrs)
 
         if "class" in attrs:
-            attrs["class"] += " django-select2"
+            attrs["class"] += " " + self.css_class_name
         else:
-            attrs["class"] = "django-select2"
+            attrs["class"] = self.css_class_name
         return attrs
 
     def optgroups(self, name, value, attrs=None):
@@ -137,6 +142,20 @@ def media(self):
         )
 
 
+class Select2AdminMixin:
+    """Select2 mixin that uses Django's own select template."""
+
+    css_class_name = "admin-autocomplete"
+    theme = "admin-autocomplete"
+
+    @property
+    def media(self):
+        return forms.Media(
+            js=Select2Mixin().media._js,
+            css=AutocompleteMixin(None, None).media._css,
+        )
+
+
 class Select2TagMixin:
     """Mixin to add select2 tag functionality."""
 
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 5a89dfd1..dc991ed2 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -21,6 +21,7 @@
     ModelSelect2TagWidget,
     ModelSelect2Widget,
     Select2Widget,
+    Select2AdminMixin,
 )
 from tests.testapp import forms
 from tests.testapp.forms import (
@@ -175,6 +176,23 @@ def test_theme_setting(self, settings):
         assert 'data-theme="classic"' in widget.render("name", None)
 
 
+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",
+            "django_select2/django_select2.js",
+        )
+
+        assert dict(Select2AdminMixin().media._css) == {
+            "screen": [
+                "admin/css/vendor/select2/select2.min.css",
+                "admin/css/autocomplete.css",
+            ]
+        }
+
+
 class TestSelect2MixinSettings:
     def test_default_media(self):
         sut = Select2Widget()

From b62ed592135961f91e45d81fb07379dc48ad9d43 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 7 Feb 2022 05:09:06 +0000
Subject: [PATCH 051/168] Bump actions/setup-python from 2.3.1 to 2.3.2

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.1 to 2.3.2.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2.3.1...v2.3.2)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 6 +++---
 .github/workflows/release.yml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2feb4772..2785d478 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.1
+      - uses: actions/setup-python@v2.3.2
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - uses: actions/checkout@v2.4.0
       - run: python setup.py sdist bdist_wheel
@@ -29,7 +29,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.1
+      - uses: actions/setup-python@v2.3.2
       - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v2.4.0
       - run: sudo apt-get install -y gettext graphviz
@@ -55,7 +55,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v2.3.1
+        uses: actions/setup-python@v2.3.2
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Chrome
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 047b387c..c176c751 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.1
+      - uses: actions/setup-python@v2.3.2
       - uses: actions/checkout@v2.4.0
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v2.5.1
-      - uses: actions/setup-python@v2.3.1
+      - uses: actions/setup-python@v2.3.2
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py
       - name: Upload packages

From 22dafdad0aa3e2b833eb40500ffe5765e3389bc8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 25 Feb 2022 05:07:12 +0000
Subject: [PATCH 052/168] Bump actions/setup-node from 2.5.1 to 3.0.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 2.5.1 to 3.0.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v2.5.1...v3.0.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2785d478..e558719e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v2.4.0
-      - uses: actions/setup-node@v2.5.1
+      - uses: actions/setup-node@v3.0.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index c176c751..15e67e23 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v2.5.1
+      - uses: actions/setup-node@v3.0.0
       - uses: actions/setup-python@v2.3.2
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py

From b5ee6bcd90177f46cfeea08ed0a5e27d149fbe47 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 1 Mar 2022 05:06:15 +0000
Subject: [PATCH 053/168] Bump actions/setup-python from 2.3.2 to 3

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2.3.2 to 3.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2.3.2...v3)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 6 +++---
 .github/workflows/release.yml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e558719e..b7cfe489 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.2
+      - uses: actions/setup-python@v3
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - uses: actions/checkout@v2.4.0
       - run: python setup.py sdist bdist_wheel
@@ -29,7 +29,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.2
+      - uses: actions/setup-python@v3
       - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v2.4.0
       - run: sudo apt-get install -y gettext graphviz
@@ -55,7 +55,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v2.3.2
+        uses: actions/setup-python@v3
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Chrome
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 15e67e23..612a15cf 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v2.3.2
+      - uses: actions/setup-python@v3
       - uses: actions/checkout@v2.4.0
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v3.0.0
-      - uses: actions/setup-python@v2.3.2
+      - uses: actions/setup-python@v3
       - uses: actions/checkout@v2.4.0
       - run: python set_version.py
       - name: Upload packages

From f099b26afd84dbb43127f34336a8a58a487b13ea Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 2 Mar 2022 05:10:00 +0000
Subject: [PATCH 054/168] Bump actions/checkout from 2.4.0 to 3

Bumps [actions/checkout](https://github.com/actions/checkout) from 2.4.0 to 3.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v2.4.0...v3)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 8 ++++----
 .github/workflows/release.yml | 4 ++--
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b7cfe489..0e0980b2 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -12,14 +12,14 @@ jobs:
     steps:
       - uses: actions/setup-python@v3
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
-      - uses: actions/checkout@v2.4.0
+      - uses: actions/checkout@v3
       - run: python setup.py sdist bdist_wheel
       - run: python -m twine check dist/*
 
   standardjs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v2.4.0
+      - uses: actions/checkout@v3
       - uses: actions/setup-node@v3.0.0
         with:
           node-version: '12.x'
@@ -31,7 +31,7 @@ jobs:
     steps:
       - uses: actions/setup-python@v3
       - run: python -m pip install -U setuptools wheel
-      - uses: actions/checkout@v2.4.0
+      - uses: actions/checkout@v3
       - run: sudo apt-get install -y gettext graphviz
       - run: python setup.py develop
       - run: python setup.py build_sphinx -W -b doctest -b html
@@ -65,7 +65,7 @@ jobs:
           mkdir bin
           curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
-      - uses: actions/checkout@v2.4.0
+      - uses: actions/checkout@v3
       - name: Install dependencies
         run: |
           python -m pip install --upgrade pip setuptools wheel codecov
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 612a15cf..38b1f3cd 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-python@v3
-      - uses: actions/checkout@v2.4.0
+      - uses: actions/checkout@v3
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
       - name: Build dist packages
@@ -25,7 +25,7 @@ jobs:
     steps:
       - uses: actions/setup-node@v3.0.0
       - uses: actions/setup-python@v3
-      - uses: actions/checkout@v2.4.0
+      - uses: actions/checkout@v3
       - run: python set_version.py
       - name: Upload packages
         run: npm publish

From e67069d99c866755f33a4a0973cfcd255a4e7f4c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 4 Apr 2022 05:10:36 +0000
Subject: [PATCH 055/168] Bump actions/setup-node from 3.0.0 to 3.1.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.0.0 to 3.1.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.0.0...v3.1.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0e0980b2..48b51ba9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.0.0
+      - uses: actions/setup-node@v3.1.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 38b1f3cd..9320eb8e 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v3.0.0
+      - uses: actions/setup-node@v3.1.0
       - uses: actions/setup-python@v3
       - uses: actions/checkout@v3
       - run: python set_version.py

From b292322a499e53d36196366f799fd39b49e8eb82 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 8 Apr 2022 14:39:15 +0200
Subject: [PATCH 056/168] Fix #133 -- Remove double dependency entry

---
 setup.cfg | 1 -
 1 file changed, 1 deletion(-)

diff --git a/setup.cfg b/setup.cfg
index 317db187..e61d80d4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -54,7 +54,6 @@ universal = 1
 [bdist_rpm]
 requires =
     python-django-appconf >= 2.0
-    python-django-appconf >= 0.6
 
 [aliases]
 test = pytest

From e6be444999c25374a263c70356293d9fee30e293 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 12 Apr 2022 09:47:47 +0000
Subject: [PATCH 057/168] Bump actions/setup-node from 3.1.0 to 3.1.1

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 48b51ba9..a5e8aa04 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.1.0
+      - uses: actions/setup-node@v3.1.1
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 9320eb8e..78352ac3 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v3.1.0
+      - uses: actions/setup-node@v3.1.1
       - uses: actions/setup-python@v3
       - uses: actions/checkout@v3
       - run: python set_version.py

From 0449db9468f41ed5da7683986657cfd3a3e9cea6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 17 May 2022 05:10:42 +0000
Subject: [PATCH 058/168] Bump actions/setup-node from 3.1.1 to 3.2.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.1.1 to 3.2.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.1.1...v3.2.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index a5e8aa04..7b85e5ce 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.1.1
+      - uses: actions/setup-node@v3.2.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 78352ac3..64cca2ac 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v3.1.1
+      - uses: actions/setup-node@v3.2.0
       - uses: actions/setup-python@v3
       - uses: actions/checkout@v3
       - run: python set_version.py

From d7b079ecbaa137f80dc7f1778788e6e6a72c85e5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 7 Jun 2022 05:07:52 +0000
Subject: [PATCH 059/168] Bump actions/setup-node from 3.2.0 to 3.3.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.2.0...v3.3.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7b85e5ce..12d2ee08 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.2.0
+      - uses: actions/setup-node@v3.3.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 64cca2ac..e8e524dc 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v3.2.0
+      - uses: actions/setup-node@v3.3.0
       - uses: actions/setup-python@v3
       - uses: actions/checkout@v3
       - run: python set_version.py

From 01550b901e5fba4e13467df37383cab667a5902c Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Wed, 8 Jun 2022 10:20:01 +0200
Subject: [PATCH 060/168] Fix #141 -- Create .readthedocs.yaml

---
 .readthedocs.yaml | 21 +++++++++++++++++++++
 setup.cfg         |  2 ++
 2 files changed, 23 insertions(+)
 create mode 100644 .readthedocs.yaml

diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 00000000..4fa27769
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,21 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+version: 2
+
+build:
+  os: ubuntu-20.04
+  tools:
+    python: "3.10"
+
+sphinx:
+  configuration: docs/conf.py
+
+
+python:
+  install:
+    - method: pip
+      path: .
+      extra_requirements:
+        - docs
diff --git a/setup.cfg b/setup.cfg
index e61d80d4..638154f0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -47,6 +47,8 @@ test =
     pytest-cov
     pytest-django
     selenium
+docs =
+    sphinx
 
 [bdist_wheel]
 universal = 1

From ba0de98a50a5fab2204f94bf10d6eb97f34d674a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 12 Jul 2022 05:07:51 +0000
Subject: [PATCH 061/168] Bump actions/setup-node from 3.3.0 to 3.4.0

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.3.0 to 3.4.0.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.3.0...v3.4.0)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 12d2ee08..76237e7e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.3.0
+      - uses: actions/setup-node@v3.4.0
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e8e524dc..016c32ed 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v3.3.0
+      - uses: actions/setup-node@v3.4.0
       - uses: actions/setup-python@v3
       - uses: actions/checkout@v3
       - run: python set_version.py

From be3520912bcd5b9879ce4db749272cc685f26284 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 15 Jul 2022 05:08:16 +0000
Subject: [PATCH 062/168] Bump actions/setup-node from 3.4.0 to 3.4.1

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3.4.0 to 3.4.1.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3.4.0...v3.4.1)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 76237e7e..c4f1264d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -20,7 +20,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.4.0
+      - uses: actions/setup-node@v3.4.1
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 016c32ed..04235ad7 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-node@v3.4.0
+      - uses: actions/setup-node@v3.4.1
       - uses: actions/setup-python@v3
       - uses: actions/checkout@v3
       - run: python set_version.py

From 731e176126595230377130ddd47b0a3b5c727e53 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 19 Jul 2022 09:19:49 +0000
Subject: [PATCH 063/168] Bump actions/setup-python from 3 to 4.1.0

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 4.1.0.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v4.1.0)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 6 +++---
 .github/workflows/release.yml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index c4f1264d..f0ccd223 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,7 +10,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v3
+      - uses: actions/setup-python@v4
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - uses: actions/checkout@v3
       - run: python setup.py sdist bdist_wheel
@@ -29,7 +29,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v3
+      - uses: actions/setup-python@v4
       - run: python -m pip install -U setuptools wheel
       - uses: actions/checkout@v3
       - run: sudo apt-get install -y gettext graphviz
@@ -55,7 +55,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v3
+        uses: actions/setup-python@v4
         with:
           python-version: ${{ matrix.python-version }}
       - name: Install Chrome
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 04235ad7..19101a23 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v3
+      - uses: actions/setup-python@v4
       - uses: actions/checkout@v3
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/setup-node@v3.4.1
-      - uses: actions/setup-python@v3
+      - uses: actions/setup-python@v4
       - uses: actions/checkout@v3
       - run: python set_version.py
       - name: Upload packages

From ab11ceac9a2ea13fee9eb896dbeaa651dfcf7421 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Mon, 1 Aug 2022 18:17:57 +0200
Subject: [PATCH 064/168] Set explicit python version

---
 .github/workflows/ci.yml      | 8 ++++++--
 .github/workflows/release.yml | 8 ++++++--
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f0ccd223..4e08a8cf 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -10,9 +10,11 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
+      - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
-      - uses: actions/checkout@v3
       - run: python setup.py sdist bdist_wheel
       - run: python -m twine check dist/*
 
@@ -29,9 +31,11 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
+      - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
       - run: python -m pip install -U setuptools wheel
-      - uses: actions/checkout@v3
       - run: sudo apt-get install -y gettext graphviz
       - run: python setup.py develop
       - run: python setup.py build_sphinx -W -b doctest -b html
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 19101a23..de592fa6 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,8 +8,10 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/setup-python@v4
       - uses: actions/checkout@v3
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
       - name: Install Python dependencies
         run: python -m pip install --upgrade pip setuptools wheel twine
       - name: Build dist packages
@@ -23,9 +25,11 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
+      - uses: actions/checkout@v3
       - uses: actions/setup-node@v3.4.1
       - uses: actions/setup-python@v4
-      - uses: actions/checkout@v3
+        with:
+          python-version: "3.10"
       - run: python set_version.py
       - name: Upload packages
         run: npm publish

From 08822ca3710ee37a050616467614af938a5d23d0 Mon Sep 17 00:00:00 2001
From: Adam Johnson <me@adamj.eu>
Date: Fri, 9 Sep 2022 11:57:34 +0100
Subject: [PATCH 065/168] Support Django 4.1

---
 .github/workflows/ci.yml  | 13 ++++++++-----
 setup.cfg                 |  1 +
 tests/testapp/settings.py |  6 +++++-
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4e08a8cf..abde664c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -50,12 +50,15 @@ jobs:
           - "3.8"
           - "3.9"
         django-version:
-          - "2.2.0"
-          - "3.2.0"
-          - "4.0a1"
+          - "2.2"
+          - "3.2"
+          - "4.0"
+          - "4.1"
         exclude:
           - python-version: "3.7"
-            django-version: "4.0a1"
+            django-version: "4.0"
+          - python-version: "3.7"
+            django-version: "4.1"
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
@@ -76,7 +79,7 @@ jobs:
           pip install -e .[test]
           pip install django~=${{ matrix.django-version }}
       - name: Run tests
-        run: PATH=$PATH:$(pwd)/bin py.test
+        run: PATH=$PATH:$(pwd)/bin pytest
       - run: codecov
         env:
           CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
diff --git a/setup.cfg b/setup.cfg
index 638154f0..ec11807a 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -24,6 +24,7 @@ classifier =
     Framework :: Django :: 2.2
     Framework :: Django :: 3.1
     Framework :: Django :: 4.0
+    Framework :: Django :: 4.1
 
 [options]
 include_package_data = True
diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py
index f46d128d..15b29b59 100644
--- a/tests/testapp/settings.py
+++ b/tests/testapp/settings.py
@@ -1,5 +1,7 @@
 import os.path
 
+import django
+
 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
 DEBUG = True
 
@@ -37,5 +39,7 @@
 
 SECRET_KEY = "123456"
 
-USE_L10N = True
+if django.VERSION < (4, 0):
+    USE_L10N = True
 USE_I18N = True
+USE_TZ = True

From a5aafd7cec43390c69ca3f5c7bd0f0824e214823 Mon Sep 17 00:00:00 2001
From: Adam Johnson <me@adamj.eu>
Date: Fri, 9 Sep 2022 12:10:40 +0100
Subject: [PATCH 066/168] Python 3.10, fix for removals in selenium

---
 .github/workflows/ci.yml |  1 +
 setup.cfg                |  1 +
 tests/test_forms.py      | 64 ++++++++++++++++++++--------------------
 3 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index abde664c..8e9a0ccf 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -49,6 +49,7 @@ jobs:
           - "3.7"
           - "3.8"
           - "3.9"
+          - "3.10"
         django-version:
           - "2.2"
           - "3.2"
diff --git a/setup.cfg b/setup.cfg
index ec11807a..e75f3704 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,6 +20,7 @@ classifier =
     Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
+    Programming Language :: Python :: 3.10
     Framework :: Django
     Framework :: Django :: 2.2
     Framework :: Django :: 3.1
diff --git a/tests/test_forms.py b/tests/test_forms.py
index dc991ed2..70a89d55 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -85,22 +85,22 @@ def test_allow_clear(self, db):
     def test_no_js_error(self, db, live_server, driver):
         driver.get(live_server + self.url)
         with pytest.raises(NoSuchElementException):
-            error = driver.find_element_by_xpath("//body[@JSError]")
+            error = driver.find_element(By.XPATH, "//body[@JSError]")
             pytest.fail(error.get_attribute("JSError"))
 
     def test_selecting(self, db, live_server, driver):
         driver.get(live_server + self.url)
         with pytest.raises(NoSuchElementException):
-            driver.find_element_by_css_selector(".select2-results")
-        elem = driver.find_element_by_css_selector(".select2-selection")
+            driver.find_element(By.CSS_SELECTOR, ".select2-results")
+        elem = driver.find_element(By.CSS_SELECTOR, ".select2-selection")
         elem.click()
-        results = driver.find_element_by_css_selector(".select2-results")
+        results = driver.find_element(By.CSS_SELECTOR, ".select2-results")
         assert results.is_displayed() is True
-        elem = results.find_element_by_css_selector(".select2-results__option")
+        elem = results.find_element(By.CSS_SELECTOR, ".select2-results__option")
         elem.click()
 
         with pytest.raises(NoSuchElementException):
-            error = driver.find_element_by_xpath("//body[@JSError]")
+            error = driver.find_element(By.XPATH, "//body[@JSError]")
             pytest.fail(error.get_attribute("JSError"))
 
     def test_data_url(self):
@@ -301,12 +301,12 @@ def test_many_selected_option(self, db, genres):
     def test_multiple_widgets(self, db, live_server, driver):
         driver.get(live_server + self.url)
         with pytest.raises(NoSuchElementException):
-            driver.find_element_by_css_selector(".select2-results")
+            driver.find_element(By.CSS_SELECTOR, ".select2-results")
 
-        elem1, elem2 = driver.find_elements_by_css_selector(".select2-selection")
+        elem1, elem2 = driver.find_elements(By.CSS_SELECTOR, ".select2-selection")
 
         elem1.click()
-        search1 = driver.find_element_by_css_selector(".select2-search__field")
+        search1 = driver.find_element(By.CSS_SELECTOR, ".select2-search__field")
         search1.send_keys("fo")
         result1 = (
             WebDriverWait(driver, 60)
@@ -319,7 +319,7 @@ def test_multiple_widgets(self, db, live_server, driver):
         )
 
         elem2.click()
-        search2 = driver.find_element_by_css_selector(".select2-search__field")
+        search2 = driver.find_element(By.CSS_SELECTOR, ".select2-search__field")
         search2.send_keys("fo")
         result2 = (
             WebDriverWait(driver, 60)
@@ -334,7 +334,7 @@ def test_multiple_widgets(self, db, live_server, driver):
         assert result1 != result2
 
         with pytest.raises(NoSuchElementException):
-            error = driver.find_element_by_xpath("//body[@JSError]")
+            error = driver.find_element(By.XPATH, "//body[@JSError]")
             pytest.fail(error.get_attribute("JSError"))
 
     def test_get_url(self):
@@ -646,15 +646,15 @@ def test_widgets_selected_after_validation_error(self, db, live_server, driver):
         WebDriverWait(driver, 3).until(
             expected_conditions.presence_of_element_located((By.ID, "id_title"))
         )
-        title = driver.find_element_by_id("id_title")
+        title = driver.find_element(By.ID, "id_title")
         title.send_keys("fo")
-        genres, fartists = driver.find_elements_by_css_selector(
-            ".select2-selection--multiple"
+        genres, fartists = driver.find_elements(
+            By.CSS_SELECTOR, ".select2-selection--multiple"
         )
         genres.click()
         genres.send_keys("o")  # results are Zero One Two Four
         # select second element - One
-        driver.find_element_by_css_selector(".select2-results li:nth-child(2)").click()
+        driver.find_element(By.CSS_SELECTOR, ".select2-results li:nth-child(2)").click()
         genres.submit()
         # there is a ValidationError raised, check for it
         errstring = (
@@ -668,8 +668,8 @@ def test_widgets_selected_after_validation_error(self, db, live_server, driver):
         )
         assert errstring == "Title must have more than 3 characters."
         # genres should still have One as selected option
-        result_title = driver.find_element_by_css_selector(
-            ".select2-selection--multiple li"
+        result_title = driver.find_element(
+            By.CSS_SELECTOR, ".select2-selection--multiple li"
         ).get_attribute("title")
         assert result_title == "One"
 
@@ -692,7 +692,7 @@ def test_widgets_selected_after_validation_error(
             country_container,
             city_container,
             city2_container,
-        ) = driver.find_elements_by_css_selector(".select2-selection--single")
+        ) = driver.find_elements(By.CSS_SELECTOR, ".select2-selection--single")
 
         # clicking city select2 lists all available cities
         city_container.click()
@@ -701,7 +701,7 @@ def test_widgets_selected_after_validation_error(
                 (By.CSS_SELECTOR, ".select2-results li")
             )
         )
-        city_options = driver.find_elements_by_css_selector(".select2-results li")
+        city_options = driver.find_elements(By.CSS_SELECTOR, ".select2-results li")
         city_names_from_browser = {option.text for option in city_options}
         city_names_from_db = set(City.objects.values_list("name", flat=True))
         assert len(city_names_from_browser) == City.objects.count()
@@ -714,8 +714,8 @@ def test_widgets_selected_after_validation_error(
                 (By.CSS_SELECTOR, ".select2-results li:nth-child(2)")
             )
         )
-        country_option = driver.find_element_by_css_selector(
-            ".select2-results li:nth-child(2)"
+        country_option = driver.find_element(
+            By.CSS_SELECTOR, ".select2-results li:nth-child(2)"
         )
         country_name = country_option.text
         country_option.click()
@@ -728,7 +728,7 @@ def test_widgets_selected_after_validation_error(
                 (By.CSS_SELECTOR, ".select2-results li")
             )
         )
-        city_options = driver.find_elements_by_css_selector(".select2-results li")
+        city_options = driver.find_elements(By.CSS_SELECTOR, ".select2-results li")
         city_names_from_browser = {option.text for option in city_options}
         city_names_from_db = set(
             Country.objects.get(name=country_name).cities.values_list("name", flat=True)
@@ -737,8 +737,8 @@ def test_widgets_selected_after_validation_error(
         assert city_names_from_browser == city_names_from_db
 
         # selecting a city reaaly does it
-        city_option = driver.find_element_by_css_selector(
-            ".select2-results li:nth-child(2)"
+        city_option = driver.find_element(
+            By.CSS_SELECTOR, ".select2-results li:nth-child(2)"
         )
         city_name = city_option.text
         city_option.click()
@@ -751,7 +751,7 @@ def test_widgets_selected_after_validation_error(
                 (By.CSS_SELECTOR, ".select2-results li")
             )
         )
-        country_options = driver.find_elements_by_css_selector(".select2-results li")
+        country_options = driver.find_elements(By.CSS_SELECTOR, ".select2-results li")
         country_names_from_browser = {option.text for option in country_options}
         country_names_from_db = {City.objects.get(name=city_name).country.name}
         assert len(country_names_from_browser) != Country.objects.count()
@@ -765,7 +765,7 @@ def test_dependent_fields_clear_after_change_parent(
             country_container,
             city_container,
             city2_container,
-        ) = driver.find_elements_by_css_selector(".select2-selection--single")
+        ) = driver.find_elements(By.CSS_SELECTOR, ".select2-selection--single")
 
         # selecting a country really does it
         country_container.click()
@@ -774,8 +774,8 @@ def test_dependent_fields_clear_after_change_parent(
                 (By.CSS_SELECTOR, ".select2-results li:nth-child(2)")
             )
         )
-        country_option = driver.find_element_by_css_selector(
-            ".select2-results li:nth-child(2)"
+        country_option = driver.find_element(
+            By.CSS_SELECTOR, ".select2-results li:nth-child(2)"
         )
         country_name = country_option.text
         country_option.click()
@@ -788,8 +788,8 @@ def test_dependent_fields_clear_after_change_parent(
                 (By.CSS_SELECTOR, ".select2-results li")
             )
         )
-        city2_option = driver.find_element_by_css_selector(
-            ".select2-results li:nth-child(2)"
+        city2_option = driver.find_element(
+            By.CSS_SELECTOR, ".select2-results li:nth-child(2)"
         )
         city2_name = city2_option.text
         city2_option.click()
@@ -802,8 +802,8 @@ def test_dependent_fields_clear_after_change_parent(
                 (By.CSS_SELECTOR, ".select2-results li:nth-child(3)")
             )
         )
-        country_option = driver.find_element_by_css_selector(
-            ".select2-results li:nth-child(3)"
+        country_option = driver.find_element(
+            By.CSS_SELECTOR, ".select2-results li:nth-child(3)"
         )
         country_name = country_option.text
         country_option.click()

From 4a6122dae5aede2d957658afc796dcef85358bd7 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 9 Sep 2022 15:01:55 +0200
Subject: [PATCH 067/168] Remove Python 3.7 support

---
 .github/workflows/ci.yml | 6 ------
 setup.cfg                | 2 --
 2 files changed, 8 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8e9a0ccf..06d750d1 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -46,7 +46,6 @@ jobs:
     strategy:
       matrix:
         python-version:
-          - "3.7"
           - "3.8"
           - "3.9"
           - "3.10"
@@ -55,11 +54,6 @@ jobs:
           - "3.2"
           - "4.0"
           - "4.1"
-        exclude:
-          - python-version: "3.7"
-            django-version: "4.0"
-          - python-version: "3.7"
-            django-version: "4.1"
     runs-on: ubuntu-latest
     steps:
       - name: Set up Python ${{ matrix.python-version }}
diff --git a/setup.cfg b/setup.cfg
index e75f3704..d386afe4 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -16,8 +16,6 @@ classifier =
     Programming Language :: Python
     Programming Language :: Python :: 3
     Programming Language :: Python :: 3 :: Only
-    Programming Language :: Python :: 3.6
-    Programming Language :: Python :: 3.7
     Programming Language :: Python :: 3.8
     Programming Language :: Python :: 3.9
     Programming Language :: Python :: 3.10

From bd9d1a5d8fc0c490c8fcbf3bf0b30a397bcdc175 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 9 Sep 2022 15:02:22 +0200
Subject: [PATCH 068/168] Remove Django 2.2 support

---
 .github/workflows/ci.yml | 1 -
 setup.cfg                | 5 ++---
 2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 06d750d1..f49ecb46 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -50,7 +50,6 @@ jobs:
           - "3.9"
           - "3.10"
         django-version:
-          - "2.2"
           - "3.2"
           - "4.0"
           - "4.1"
diff --git a/setup.cfg b/setup.cfg
index d386afe4..c23691a0 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,8 +20,7 @@ classifier =
     Programming Language :: Python :: 3.9
     Programming Language :: Python :: 3.10
     Framework :: Django
-    Framework :: Django :: 2.2
-    Framework :: Django :: 3.1
+    Framework :: Django :: 3.2
     Framework :: Django :: 4.0
     Framework :: Django :: 4.1
 
@@ -29,7 +28,7 @@ classifier =
 include_package_data = True
 packages = django_select2
 install_requires =
-    django>=2.2
+    django>=3.2
     django-appconf>=0.6.0
 setup_requires =
     setuptools_scm

From 245450dc821f7710f3e030110b3bb5da4d5acc96 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 9 Sep 2022 15:02:43 +0200
Subject: [PATCH 069/168] Fix Django version install in CI

---
 .github/workflows/ci.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f49ecb46..e0e31986 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -71,7 +71,7 @@ jobs:
         run: |
           python -m pip install --upgrade pip setuptools wheel codecov
           pip install -e .[test]
-          pip install django~=${{ matrix.django-version }}
+          pip install django~="${{ matrix.django-version }}.0"
       - name: Run tests
         run: PATH=$PATH:$(pwd)/bin pytest
       - run: codecov

From 371c2235000d59f5355569b81b59d0eeb8223a45 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 9 Sep 2022 15:16:05 +0200
Subject: [PATCH 070/168] Update CI suite

---
 .github/workflows/ci.yml      | 48 +++++++++++++++++++++--------------
 .github/workflows/release.yml | 12 ++++-----
 setup.cfg                     |  9 ++-----
 3 files changed, 36 insertions(+), 33 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e0e31986..f2b2b8f4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -2,7 +2,7 @@ name: CI
 on:
   push:
     branches:
-      - master
+      - main
   pull_request:
 
 jobs:
@@ -13,7 +13,7 @@ jobs:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
         with:
-          python-version: "3.10"
+          python-version: "3.x"
       - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
       - run: python setup.py sdist bdist_wheel
       - run: python -m twine check dist/*
@@ -35,12 +35,11 @@ jobs:
       - uses: actions/setup-python@v4
         with:
           python-version: "3.10"
-      - run: python -m pip install -U setuptools wheel
       - run: sudo apt-get install -y gettext graphviz
-      - run: python setup.py develop
-      - run: python setup.py build_sphinx -W -b doctest -b html
+      - run: python -m pip install -e .[docs]
+      - run: python -m sphinx -W -b doctest -b html docs docs/_build
 
-  pytest:
+  PyTest:
     needs:
       - standardjs
     strategy:
@@ -55,10 +54,25 @@ jobs:
           - "4.1"
     runs-on: ubuntu-latest
     steps:
-      - name: Set up Python ${{ matrix.python-version }}
-        uses: actions/setup-python@v4
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v4
         with:
           python-version: ${{ matrix.python-version }}
+      - run: python -m pip install Django~="${{ matrix.django-version }}.0"
+      - run: python -m pip install -e .[test]
+      - run: python -m pytest
+      - uses: codecov/codecov-action@v2
+
+  Selenium:
+    needs:
+      - standardjs
+    strategy:
+      matrix:
+        python-version:
+          - "3.x"
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
       - name: Install Chrome
         run: sudo apt-get install -y google-chrome-stable
       - name: Install Selenium
@@ -66,14 +80,10 @@ jobs:
           mkdir bin
           curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
-      - uses: actions/checkout@v3
-      - name: Install dependencies
-        run: |
-          python -m pip install --upgrade pip setuptools wheel codecov
-          pip install -e .[test]
-          pip install django~="${{ matrix.django-version }}.0"
-      - name: Run tests
-        run: PATH=$PATH:$(pwd)/bin pytest
-      - run: codecov
-        env:
-          CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}
+      - uses: actions/setup-python@v4
+        with:
+          python-version: ${{ matrix.python-version }}
+      - run: python -m pip install Django
+      - run: python -m pip install -e .[test,selenium]
+      - run: python -m pytest
+      - uses: codecov/codecov-action@v2
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index de592fa6..12bfe59f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -11,13 +11,11 @@ jobs:
       - uses: actions/checkout@v3
       - uses: actions/setup-python@v4
         with:
-          python-version: "3.10"
-      - name: Install Python dependencies
-        run: python -m pip install --upgrade pip setuptools wheel twine
+          python-version: "3.x"
+      - run: python -m pip install --upgrade pip build wheel twine
       - name: Build dist packages
-        run: python setup.py sdist bdist_wheel
-      - name: Upload packages
-        run: python -m twine upload dist/*
+        run: python -m build --sdist --wheel
+      - run: python -m twine upload dist/*
         env:
           TWINE_USERNAME: __token__
           TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
@@ -29,7 +27,7 @@ jobs:
       - uses: actions/setup-node@v3.4.1
       - uses: actions/setup-python@v4
         with:
-          python-version: "3.10"
+          python-version: "3.x"
       - run: python set_version.py
       - name: Upload packages
         run: npm publish
diff --git a/setup.cfg b/setup.cfg
index c23691a0..f02b95dc 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -32,13 +32,6 @@ install_requires =
     django-appconf>=0.6.0
 setup_requires =
     setuptools_scm
-    sphinx
-    pytest-runner
-tests_require =
-    pytest
-    pytest-cov
-    pytest-django
-    selenium
 
 [options.extras_require]
 test =
@@ -46,6 +39,8 @@ test =
     pytest-cov
     pytest-django
     selenium
+selenium =
+    selenium
 docs =
     sphinx
 

From a96ad8e27c100967066255a020f78e602baf382e Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 9 Sep 2022 15:54:14 +0200
Subject: [PATCH 071/168] Simplify GH action version setup

---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f2b2b8f4..f4ee680a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,7 +22,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.4.1
+      - uses: actions/setup-node@v3
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 12bfe59f..f8e3b587 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
-      - uses: actions/setup-node@v3.4.1
+      - uses: actions/setup-node@v3
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"

From f5ebb24f3eb8105959a9f77d20d41c110d356346 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 12 Sep 2022 05:08:18 +0000
Subject: [PATCH 072/168] Bump codecov/codecov-action from 2 to 3

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 2 to 3.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f4ee680a..ff5413ab 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -61,7 +61,7 @@ jobs:
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
       - run: python -m pip install -e .[test]
       - run: python -m pytest
-      - uses: codecov/codecov-action@v2
+      - uses: codecov/codecov-action@v3
 
   Selenium:
     needs:
@@ -86,4 +86,4 @@ jobs:
       - run: python -m pip install Django
       - run: python -m pip install -e .[test,selenium]
       - run: python -m pytest
-      - uses: codecov/codecov-action@v2
+      - uses: codecov/codecov-action@v3

From 1f6ac37964a83ff392d51e240d6de9ff00bed413 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 14 Oct 2022 10:30:47 +0200
Subject: [PATCH 073/168] Add tidelift security information

---
 SECURITY.md | 7 +++++++
 1 file changed, 7 insertions(+)
 create mode 100644 SECURITY.md

diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000..b0208c5f
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,7 @@
+# Security
+
+## Security contact information
+
+To report a security vulnerability, please use the
+[Tidelift security contact](https://tidelift.com/security).
+Tidelift will coordinate the fix and disclosure.

From a2fa381ac7ae560d9fa801b26370866e8c6161f8 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 22 Oct 2022 11:10:20 +0200
Subject: [PATCH 074/168] Add tidelift funding link

---
 .github/FUNDING.yml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index ae3c5338..da739aec 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,2 +1,3 @@
 github: codingjoe
+tidelift: pypi/django-select2
 custom: https://paypal.me/codingjoe

From 7215346187573907b860220dbe0640f2c7776a0c Mon Sep 17 00:00:00 2001
From: Karl <karlwooster@gmail.com>
Date: Fri, 5 Aug 2022 15:31:43 -0700
Subject: [PATCH 075/168] Add clarification about widget types

Help users save time in the event that they're trying to use these extra features with a light widget where it will not work.
---
 docs/extra.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/docs/extra.rst b/docs/extra.rst
index c3524ce7..0865d77c 100644
--- a/docs/extra.rst
+++ b/docs/extra.rst
@@ -8,6 +8,9 @@ Suppose you have an address form where a user should choose a Country and a City
 When the user selects a country we want to show only cities belonging to that country.
 So the one selector depends on another one.
 
+.. note::
+    Does not work with the 'light' version (django_select2.forms.Select2Widget).
+
 Models
 ``````
 

From 5a635feba14b180c6d4821c2e56e6b518c8e921a Mon Sep 17 00:00:00 2001
From: N1K1TAS95 <46042802+N1K1TAS95@users.noreply.github.com>
Date: Sun, 30 Oct 2022 23:02:05 +0100
Subject: [PATCH 076/168] Resolve #159 -- Add custom JSONEncoder support via
 setting (#160)

---
 django_select2/conf.py  | 8 ++++++++
 django_select2/views.py | 4 +++-
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/django_select2/conf.py b/django_select2/conf.py
index 8862932a..a3117014 100644
--- a/django_select2/conf.py
+++ b/django_select2/conf.py
@@ -198,6 +198,14 @@ class Select2Conf(AppConf):
     ``settings.DJANGO_SELECT2_I18N`` refers to :attr:`.I18N_PATH`.
     """
 
+    JSON_ENCODER = 'django.core.serializers.json.DjangoJSONEncoder'
+    """
+    A :class:`JSONEncoder<json.JSONEncoder>` used to generate the API response for the model widgets.
+
+    A custom JSON encoder might be useful when your models uses
+    a special primary key, that isn't serializable by the default encoder.
+    """
+
     class Meta:
         """Prefix for all Django-Select2 settings."""
 
diff --git a/django_select2/views.py b/django_select2/views.py
index c03f683e..0af69b64 100644
--- a/django_select2/views.py
+++ b/django_select2/views.py
@@ -3,6 +3,7 @@
 from django.core.signing import BadSignature
 from django.http import Http404, JsonResponse
 from django.views.generic.list import BaseListView
+from django.utils.module_loading import import_string
 
 from .cache import cache
 from .conf import settings
@@ -43,7 +44,8 @@ def get(self, request, *args, **kwargs):
                     for obj in context["object_list"]
                 ],
                 "more": context["page_obj"].has_next(),
-            }
+            },
+            encoder=import_string(settings.SELECT2_JSON_ENCODER)
         )
 
     def get_queryset(self):

From d410f22254a0761f1af583ef4d0d80765279084e Mon Sep 17 00:00:00 2001
From: Kevin Ramirez <kvnzavalza@hotmail.com>
Date: Thu, 3 Nov 2022 01:56:00 -0600
Subject: [PATCH 077/168] Fix #79 -- Clear values of related fields (#137)

Co-authored-by: Kevin Ramirez <kevin.ramirez@mandarinprojects.mx>
---
 django_select2/static/django_select2/django_select2.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_select2/static/django_select2/django_select2.js b/django_select2/static/django_select2/django_select2.js
index 200534ba..f2358df0 100644
--- a/django_select2/static/django_select2/django_select2.js
+++ b/django_select2/static/django_select2/django_select2.js
@@ -59,7 +59,7 @@
       }
       $element.on('select2:select', function (e) {
         var name = $(e.currentTarget).attr('name')
-        $('[data-select2-dependent-fields=' + name + ']').each(function () {
+        $('[data-select2-dependent-fields~=' + name + ']').each(function () {
           $(this).val('').trigger('change')
         })
       })

From b568368cb68045db772a3166f1cf80804d096202 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Thu, 3 Nov 2022 16:28:58 +0100
Subject: [PATCH 078/168] Add header image

---
 README.rst | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/README.rst b/README.rst
index 11f5f469..81cf3e09 100644
--- a/README.rst
+++ b/README.rst
@@ -1,12 +1,12 @@
+|header|
+
 ==============
 Django-Select2
 ==============
 
 |version| |coverage| |license|
 
-This is a `Django`_ integration of `Select2`_.
-
-The app includes Select2 driven Django Widgets.
+Custom autocompelte fields for `Django`_.
 
 Documentation
 -------------
@@ -22,6 +22,7 @@ Documentation available at https://django-select2.readthedocs.io/.
 .. _Select2: https://select2.org/
 .. _autocomplete_fields: https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
 
+.. |header| image:: https://repository-images.githubusercontent.com/266545281/c6db7d26-9f60-454b-845e-395d45c43fa7
 .. |version| image:: https://img.shields.io/pypi/v/Django-Select2.svg
    :target: https://pypi.python.org/pypi/Django-Select2/
 .. |coverage| image:: https://codecov.io/gh/codingjoe/django-select2/branch/master/graph/badge.svg

From e62b8ea7e86aad3efd8f586f8836c3c28f8678ce Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 12:04:55 +0100
Subject: [PATCH 079/168] Add selenium test marker to stablize CI suite

---
 .github/workflows/ci.yml | 4 ++--
 tests/conftest.py        | 5 +++++
 tests/test_forms.py      | 6 ++++++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ff5413ab..ddd59a2e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -60,7 +60,7 @@ jobs:
           python-version: ${{ matrix.python-version }}
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
       - run: python -m pip install -e .[test]
-      - run: python -m pytest
+      - run: python -m pytest -m "not selenium"
       - uses: codecov/codecov-action@v3
 
   Selenium:
@@ -85,5 +85,5 @@ jobs:
           python-version: ${{ matrix.python-version }}
       - run: python -m pip install Django
       - run: python -m pip install -e .[test,selenium]
-      - run: python -m pytest
+      - run: python -m pytest -m selenium
       - uses: codecov/codecov-action@v3
diff --git a/tests/conftest.py b/tests/conftest.py
index b5e37416..3ac31e51 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -6,6 +6,11 @@
 from selenium.common.exceptions import WebDriverException
 
 
+def pytest_configure(config):
+  config.addinivalue_line(
+        "markers", "selenium: skip if selenium is not installed"
+  )
+
 def random_string(n):
     return "".join(
         random.choice(string.ascii_uppercase + string.digits) for _ in range(n)
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 70a89d55..6e81f50b 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -82,12 +82,14 @@ def test_allow_clear(self, db):
             "primary_genre", None
         )
 
+    @pytest.mark.selenium
     def test_no_js_error(self, db, live_server, driver):
         driver.get(live_server + self.url)
         with pytest.raises(NoSuchElementException):
             error = driver.find_element(By.XPATH, "//body[@JSError]")
             pytest.fail(error.get_attribute("JSError"))
 
+    @pytest.mark.selenium
     def test_selecting(self, db, live_server, driver):
         driver.get(live_server + self.url)
         with pytest.raises(NoSuchElementException):
@@ -298,6 +300,7 @@ def test_many_selected_option(self, db, genres):
         ), widget_output
         assert selected_option2 in widget_output or selected_option2a in widget_output
 
+    @pytest.mark.selenium
     def test_multiple_widgets(self, db, live_server, driver):
         driver.get(live_server + self.url)
         with pytest.raises(NoSuchElementException):
@@ -641,6 +644,7 @@ class TestHeavySelect2MultipleWidget:
         bool(os.environ.get("CI", False)),
         reason="https://bugs.chromium.org/p/chromedriver/issues/detail?id=1772",
     )
+    @pytest.mark.selenium
     def test_widgets_selected_after_validation_error(self, db, live_server, driver):
         driver.get(live_server + self.url)
         WebDriverWait(driver, 3).until(
@@ -678,6 +682,7 @@ class TestAddressChainedSelect2Widget:
     url = reverse("model_chained_select2_widget")
     form = forms.AddressChainedSelect2WidgetForm()
 
+    @pytest.mark.selenium
     def test_widgets_selected_after_validation_error(
         self, db, live_server, driver, countries, cities
     ):
@@ -757,6 +762,7 @@ def test_widgets_selected_after_validation_error(
         assert len(country_names_from_browser) != Country.objects.count()
         assert country_names_from_browser == country_names_from_db
 
+    @pytest.mark.selenium
     def test_dependent_fields_clear_after_change_parent(
         self, db, live_server, driver, countries, cities
     ):

From cc834af3934488c1e98f8fc483835f00b5d10e9d Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 12:08:58 +0100
Subject: [PATCH 080/168] Repleace fussyfox with GH actions

---
 .fussyfox.yml            |  5 -----
 .github/workflows/ci.yml | 22 ++++++++++++++++++++++
 linter-requirements.txt  |  5 +++++
 3 files changed, 27 insertions(+), 5 deletions(-)
 delete mode 100644 .fussyfox.yml
 create mode 100644 linter-requirements.txt

diff --git a/.fussyfox.yml b/.fussyfox.yml
deleted file mode 100644
index 6a17e6bd..00000000
--- a/.fussyfox.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-- bandit
-- black
-- flake8
-- isort
-- pydocstyle
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ddd59a2e..042d813a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -7,6 +7,26 @@ on:
 
 jobs:
 
+  lint:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        lint-command:
+          - bandit -r . -x ./tests
+          - black --check --diff .
+          - flake8 .
+          - isort --check-only --diff .
+          - pydocstyle .
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.x"
+          cache: 'pip'
+          cache-dependency-path: 'linter-requirements.txt'
+      - run: python -m pip install -r linter-requirements.txt
+      - run: ${{ matrix.lint-command }}
+
   dist:
     runs-on: ubuntu-latest
     steps:
@@ -41,6 +61,7 @@ jobs:
 
   PyTest:
     needs:
+      - lint
       - standardjs
     strategy:
       matrix:
@@ -65,6 +86,7 @@ jobs:
 
   Selenium:
     needs:
+      - lint
       - standardjs
     strategy:
       matrix:
diff --git a/linter-requirements.txt b/linter-requirements.txt
new file mode 100644
index 00000000..c3083bcb
--- /dev/null
+++ b/linter-requirements.txt
@@ -0,0 +1,5 @@
+bandit==1.7.4
+black==22.10.0
+flake8==5.0.4
+isort==5.10.1
+pydocstyle[toml]==6.1.1

From 5894b52ea7303fde4fb58c23172f5240d89a2aef Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 12:10:00 +0100
Subject: [PATCH 081/168] Reformat code using black & isort

---
 django_select2/conf.py  | 2 +-
 django_select2/views.py | 4 ++--
 tests/conftest.py       | 5 ++---
 tests/test_forms.py     | 2 +-
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/django_select2/conf.py b/django_select2/conf.py
index a3117014..03ebe7dd 100644
--- a/django_select2/conf.py
+++ b/django_select2/conf.py
@@ -198,7 +198,7 @@ class Select2Conf(AppConf):
     ``settings.DJANGO_SELECT2_I18N`` refers to :attr:`.I18N_PATH`.
     """
 
-    JSON_ENCODER = 'django.core.serializers.json.DjangoJSONEncoder'
+    JSON_ENCODER = "django.core.serializers.json.DjangoJSONEncoder"
     """
     A :class:`JSONEncoder<json.JSONEncoder>` used to generate the API response for the model widgets.
 
diff --git a/django_select2/views.py b/django_select2/views.py
index 0af69b64..1665dbd5 100644
--- a/django_select2/views.py
+++ b/django_select2/views.py
@@ -2,8 +2,8 @@
 from django.core import signing
 from django.core.signing import BadSignature
 from django.http import Http404, JsonResponse
-from django.views.generic.list import BaseListView
 from django.utils.module_loading import import_string
+from django.views.generic.list import BaseListView
 
 from .cache import cache
 from .conf import settings
@@ -45,7 +45,7 @@ def get(self, request, *args, **kwargs):
                 ],
                 "more": context["page_obj"].has_next(),
             },
-            encoder=import_string(settings.SELECT2_JSON_ENCODER)
+            encoder=import_string(settings.SELECT2_JSON_ENCODER),
         )
 
     def get_queryset(self):
diff --git a/tests/conftest.py b/tests/conftest.py
index 3ac31e51..60bbe399 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -7,9 +7,8 @@
 
 
 def pytest_configure(config):
-  config.addinivalue_line(
-        "markers", "selenium: skip if selenium is not installed"
-  )
+    config.addinivalue_line("markers", "selenium: skip if selenium is not installed")
+
 
 def random_string(n):
     return "".join(
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 6e81f50b..621a24e1 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -20,8 +20,8 @@
     HeavySelect2Widget,
     ModelSelect2TagWidget,
     ModelSelect2Widget,
-    Select2Widget,
     Select2AdminMixin,
+    Select2Widget,
 )
 from tests.testapp import forms
 from tests.testapp.forms import (

From 10d5e8d681fc0bd38b3520e3f51bbd7fb9eeafac Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 11:50:59 +0100
Subject: [PATCH 082/168] Fix #163 -- Lazily get i18n locale name

A widget instance can leak the i18n setting to another request
or be stuck on the default language setting.
---
 django_select2/forms.py |  7 ++++---
 tests/test_forms.py     | 25 ++++++++++++++-----------
 2 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index df3982fe..5e2ea5fd 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -86,9 +86,10 @@ class Select2Mixin:
 
     empty_label = ""
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.i18n_name = SELECT2_TRANSLATIONS.get(get_language())
+    @property
+    def i18n_name(self):
+        """Name of the i18n file for the current language."""
+        return SELECT2_TRANSLATIONS.get(get_language())
 
     def build_attrs(self, base_attrs, extra_attrs=None):
         """Add select2 data attributes."""
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 621a24e1..4e148f7a 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -3,7 +3,6 @@
 from collections.abc import Iterable
 
 import pytest
-from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
 from django.db.models import QuerySet
 from django.urls import reverse
 from django.utils import translation
@@ -48,11 +47,16 @@ def test_initial_form_class(self):
         assert "my-class" in widget.render("name", None)
         assert "django-select2" in widget.render("name", None)
 
-    @pytest.mark.parametrize("code,name", SELECT2_TRANSLATIONS.items())
-    def test_lang_attr(self, code, name):
-        translation.activate(code)
-        widget = self.widget_cls()
-        assert f'lang="{name}"' in widget.render("name", None)
+    def test_lang_attr(self):
+        with translation.override("de"):
+            widget = Select2Widget()
+            assert 'lang="de"' in widget.render("name", None)
+
+        # Regression test for #163
+        widget = Select2Widget()
+        assert widget.i18n_name == "en"
+        with translation.override("de"):
+            assert widget.i18n_name == "de"
 
     def test_allow_clear(self, db):
         required_field = self.form.fields["artist"]
@@ -258,11 +262,10 @@ def test_initial_form_class(self):
             "name", None
         )
 
-    @pytest.mark.parametrize("code,name", SELECT2_TRANSLATIONS.items())
-    def test_lang_attr(self, code, name):
-        translation.activate(code)
-        widget = self.widget_cls(data_view="heavy_data_1")
-        assert f'lang="{name}"' in widget.render("name", None)
+    def test_lang_attr(self):
+        with translation.override("fr"):
+            widget = self.widget_cls(data_view="heavy_data_1")
+            assert 'lang="fr"' in widget.render("name", None)
 
     def test_selected_option(self, db):
         not_required_field = self.form.fields["primary_genre"]

From 15790a3dd54f66cd03879497f5016052cf4da9b1 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 13:38:41 +0100
Subject: [PATCH 083/168] Update packaging to pyproject.toml

---
 .editorconfig                 |  2 +-
 .github/workflows/ci.yml      |  4 +-
 .github/workflows/release.yml |  1 +
 .gitignore                    |  2 +
 LICENSE                       |  2 +-
 django_select2/__init__.py    |  5 ++
 pyproject.toml                | 89 +++++++++++++++++++++++++++++++++++
 set_version.py                |  5 +-
 setup.cfg                     | 85 +--------------------------------
 setup.py                      |  5 --
 10 files changed, 105 insertions(+), 95 deletions(-)
 create mode 100644 pyproject.toml
 delete mode 100755 setup.py

diff --git a/.editorconfig b/.editorconfig
index f69b8ec1..d7e0de91 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,7 +10,7 @@ insert_final_newline = true
 charset = utf-8
 end_of_line = lf
 
-[*.{json,yml,yaml,js,jsx}]
+[*.{json,yml,yaml,js,jsx,toml}]
 indent_size = 2
 
 [LICENSE]
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 042d813a..bc44000f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -34,8 +34,8 @@ jobs:
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"
-      - run: python -m pip install --upgrade pip setuptools wheel twine readme-renderer
-      - run: python setup.py sdist bdist_wheel
+      - run: python -m pip install --upgrade pip build wheel twine readme-renderer
+      - run: python -m build --sdist --wheel
       - run: python -m twine check dist/*
 
   standardjs:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f8e3b587..f6548af4 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -28,6 +28,7 @@ jobs:
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"
+      - run: python -m pip install --upgrade setuptools_scm
       - run: python set_version.py
       - name: Upload packages
         run: npm publish
diff --git a/.gitignore b/.gitignore
index d1ef58f6..8c43d48c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,3 +23,5 @@ ghostdriver.log
 coverage.xml
 .eggs/
 db.sqlite3
+
+_version.py
diff --git a/LICENSE b/LICENSE
index d5d8ec80..3f28e2b7 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2017 Johannes Hoppe
+Copyright (c) 2022 Johannes Maron
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/django_select2/__init__.py b/django_select2/__init__.py
index 575a0213..95783ce7 100644
--- a/django_select2/__init__.py
+++ b/django_select2/__init__.py
@@ -9,5 +9,10 @@
 """
 from django import get_version
 
+from . import _version
+
+__version__ = _version.version
+VERSION = _version.version_tuple
+
 if get_version() < "3.2":
     default_app_config = "django_select2.apps.Select2AppConfig"
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 00000000..1d4fb2f5
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,89 @@
+[build-system]
+requires = ["flit_core>=3.2", "flit_scm", "wheel"]
+build-backend = "flit_scm:buildapi"
+
+[project]
+name = "django-select2"
+authors = [
+  { name = "Johannes Maron", email = "johannes@maron.family" },
+]
+readme = "README.rst"
+license = { file = "LICENSE" }
+keywords = ["Django", "select2", "autocomplete", "typeahead"]
+dynamic = ["version", "description"]
+classifiers = [
+  "Development Status :: 5 - Production/Stable",
+  "License :: OSI Approved :: MIT License",
+  "Intended Audience :: Developers",
+  "Environment :: Web Environment",
+  "Operating System :: OS Independent",
+  "Programming Language :: Python",
+  "Programming Language :: Python :: 3",
+  "Programming Language :: Python :: 3 :: Only",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.10",
+  "Framework :: Django",
+  "Framework :: Django :: 3.2",
+  "Framework :: Django :: 4.0",
+  "Framework :: Django :: 4.1",
+  "Topic :: Software Development",
+]
+requires-python = ">=3.8"
+dependencies = [
+  "django>=3.2",
+  "django-appconf>=0.6.0"
+]
+
+[project.optional-dependencies]
+test = [
+  "pytest",
+  "pytest-cov",
+  "pytest-django",
+  "selenium",
+]
+selenium = [
+  "selenium",
+]
+docs = [
+  "sphinx",
+]
+
+[project.urls]
+Project-URL = "https://github.com/codingjoe/django-select2"
+Changelog = "https://github.com/codingjoe/django-select2/releases"
+Source = "https://github.com/codingjoe/django-select2"
+Documentation = "https://django-select2.rtfd.io/"
+Issue-Tracker = "https://github.com/codingjoe/django-select2/issues"
+
+[tool.flit.module]
+name = "django_select2"
+
+[tool.setuptools_scm]
+write_to = "django_select2/_version.py"
+
+[tool.pytest.ini_options]
+minversion = "6.0"
+addopts = "--cov --tb=short -rxs"
+testpaths = ["tests"]
+DJANGO_SETTINGS_MODULE = "tests.testapp.settings"
+
+[tool.coverage.run]
+source = ["django_select2"]
+
+[tool.coverage.report]
+show_missing = true
+
+[tool.isort]
+atomic = true
+line_length = 88
+multi_line_output = 3
+include_trailing_comma = true
+force_grid_wrap = 0
+use_parentheses = true
+known_first_party = "django_select2, tests"
+default_section = "THIRDPARTY"
+combine_as_imports = true
+
+[tool.pydocstyle]
+add_ignore = "D1"
diff --git a/set_version.py b/set_version.py
index 50ffa7bf..fa18ce33 100755
--- a/set_version.py
+++ b/set_version.py
@@ -1,12 +1,13 @@
 #!/usr/bin/env python3
 """Set the version in NPM's package.json to match the git tag."""
 import json
-import os
+
+from setuptools_scm import get_version
 
 if __name__ == "__main__":
     with open("package.json", "r+") as f:
         data = json.load(f)
         f.seek(0)
-        data["version"] = os.environ["GITHUB_REF"].rsplit("/")[-1]
+        data["version"] = get_version(root=".", relative_to=__file__)
         json.dump(data, f)
         f.truncate()
diff --git a/setup.cfg b/setup.cfg
index f02b95dc..6f60592c 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,87 +1,4 @@
-[metadata]
-name = django-select2
-author = Johannes Hoppe
-author_email = info@johanneshoppe.com
-description = Select2 option fields for Django
-long_description = file: README.rst
-url = https://github.com/codingjoe/django-select2
-license = MIT
-license_file = LICENSE
-classifier =
-    Development Status :: 5 - Production/Stable
-    Environment :: Web Environment
-    Intended Audience :: Developers
-    License :: OSI Approved :: Apache Software License
-    Operating System :: OS Independent
-    Programming Language :: Python
-    Programming Language :: Python :: 3
-    Programming Language :: Python :: 3 :: Only
-    Programming Language :: Python :: 3.8
-    Programming Language :: Python :: 3.9
-    Programming Language :: Python :: 3.10
-    Framework :: Django
-    Framework :: Django :: 3.2
-    Framework :: Django :: 4.0
-    Framework :: Django :: 4.1
-
-[options]
-include_package_data = True
-packages = django_select2
-install_requires =
-    django>=3.2
-    django-appconf>=0.6.0
-setup_requires =
-    setuptools_scm
-
-[options.extras_require]
-test =
-    pytest
-    pytest-cov
-    pytest-django
-    selenium
-selenium =
-    selenium
-docs =
-    sphinx
-
-[bdist_wheel]
-universal = 1
-
-[bdist_rpm]
-requires =
-    python-django-appconf >= 2.0
-
-[aliases]
-test = pytest
-
-[build_sphinx]
-source-dir = docs
-build-dir = docs/_build
-
-[tool:pytest]
-addopts =
-    tests
-    --doctest-glob='*.rst'
-    --doctest-modules
-    --cov=django_select2
-DJANGO_SETTINGS_MODULE=tests.testapp.settings
-
 [flake8]
 max-line-length=88
 select = C,E,F,W,B,B950
-ignore = E203, E501, W503
-exclude = venv,.tox,.eggs
-
-[pydocstyle]
-add-ignore = D1
-
-[isort]
-atomic = true
-line_length = 88
-multi_line_output = 3
-include_trailing_comma = True
-force_grid_wrap = 0
-use_parentheses = True
-known_first_party = django_select2, tests
-default_section = THIRDPARTY
-combine_as_imports = true
+ignore = E203, E501, W503, E731
diff --git a/setup.py b/setup.py
deleted file mode 100755
index f4bd8e57..00000000
--- a/setup.py
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/usr/bin/env python
-
-from setuptools import setup
-
-setup(name="django-select2", use_scm_version=True)

From 3781b67ffd4128585bcf99312f22c92e42d3e04c Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 14:24:59 +0100
Subject: [PATCH 084/168] Fix Select2AdminMixin

---
 django_select2/forms.py | 5 +++--
 tests/test_forms.py     | 1 +
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 5e2ea5fd..68be213f 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -146,14 +146,15 @@ def media(self):
 class Select2AdminMixin:
     """Select2 mixin that uses Django's own select template."""
 
-    css_class_name = "admin-autocomplete"
     theme = "admin-autocomplete"
 
     @property
     def media(self):
+        css = {**AutocompleteMixin(None, None).media._css}
+        css["screen"].append("django_select2/django_select2.css")
         return forms.Media(
             js=Select2Mixin().media._js,
-            css=AutocompleteMixin(None, None).media._css,
+            css=css,
         )
 
 
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 4e148f7a..0b7c0af7 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -195,6 +195,7 @@ def test_media(self):
             "screen": [
                 "admin/css/vendor/select2/select2.min.css",
                 "admin/css/autocomplete.css",
+                "django_select2/django_select2.css",
             ]
         }
 

From 112846cc76fa137a3946a2e71425deb9a561aa58 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Sat, 5 Nov 2022 17:42:11 +0100
Subject: [PATCH 085/168] Change default Select2 version to Django's vendored
 version

---
 django_select2/conf.py                        | 75 +++----------------
 django_select2/forms.py                       |  4 +-
 .../static/django_select2/django_select2.js   |  2 +-
 django_select2/views.py                       |  2 +-
 docs/extra.rst                                |  8 +-
 docs/index.rst                                | 18 ++++-
 example/example/settings.py                   |  6 +-
 .../example/templates/example/book_form.html  |  4 +-
 example/requirements.txt                      |  2 +-
 tests/test_forms.py                           | 39 ++++------
 tests/testapp/settings.py                     |  1 +
 tests/testapp/templates/form.html             |  7 +-
 12 files changed, 56 insertions(+), 112 deletions(-)

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 @@
-<!DOCTYPE html>
+{% load static %}<!DOCTYPE html>
 <html lang="en">
 <head>
     <title>Create Book</title>
@@ -14,7 +14,7 @@ <h1>Create a new Book</h1>
         {{ form.as_p }}
         <input type="submit">
     </form>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
+    <script src="{% static 'admin/js/vendor/jquery/jquery.min.js' %}"></script>
     {{ form.media.js }}
 </body>
 </html>
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 %}
-<!DOCTYPE html>
-<html>
+{% load static %}<!DOCTYPE html>
+<html lang="en">
 <head>
   {{ form.media.css }}
   <style type="text/css">
@@ -15,7 +14,7 @@
   {{ form }}
   <input type="submit" value="Submit Form"/>
 </form>
-<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
+<script src="{% static 'admin/js/vendor/jquery/jquery.min.js' %}"></script>
 <script type="text/javascript">
   window.onerror = function (msg) {
     $("body").attr("JSError", msg);

From ec88c6b16b8ee736a63d1ff0094a5ec1a5d40455 Mon Sep 17 00:00:00 2001
From: Klaas van Schelven <klaas@vanschelven.com>
Date: Wed, 9 Nov 2022 10:54:21 +0100
Subject: [PATCH 086/168] Correct the copyright in the licence

As this is is a multi-contributor project, and presumably the other contributors have not all transferred their copyright to Johannes, they still have the copyright to their work.
---
 LICENSE | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/LICENSE b/LICENSE
index 3f28e2b7..621b9067 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2022 Johannes Maron
+Copyright (c) 2022 Johannes Maron and other contributors
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

From 4770f069e5dd6137f725f4e16095cfd4cf9d78b6 Mon Sep 17 00:00:00 2001
From: Klaas van Schelven <klaas@vanschelven.com>
Date: Wed, 9 Nov 2022 10:04:03 +0100
Subject: [PATCH 087/168] Fix typo on first line of docs

---
 README.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.rst b/README.rst
index 81cf3e09..93d87344 100644
--- a/README.rst
+++ b/README.rst
@@ -6,7 +6,7 @@ Django-Select2
 
 |version| |coverage| |license|
 
-Custom autocompelte fields for `Django`_.
+Custom autocomplete fields for `Django`_.
 
 Documentation
 -------------

From f4eb656130fbea85b79b85398ef27ac4ced46799 Mon Sep 17 00:00:00 2001
From: robotnaoborot <robotnaoborot@gmail.com>
Date: Tue, 22 Nov 2022 22:21:41 +0300
Subject: [PATCH 088/168] Fix of documentation for ModelSelect2TagWidget

---
 django_select2/forms.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 4809d066..da7b5e0d 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -600,7 +600,7 @@ def value_from_datadict(self, data, files, name):
                 # You need to implement this method yourself, to ensure proper object creation.
                 pks = self.queryset.filter(**{'pk__in': list(values)}).values_list('pk', flat=True)
                 pks = set(map(str, pks))
-                cleaned_values = list(values)
+                cleaned_values = list(pks)
                 for val in values - pks:
                     cleaned_values.append(self.queryset.create(title=val).pk)
                 return cleaned_values

From 7cf9586b8be521471e78ae2989d6d4d09afd4253 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 24 Nov 2022 05:02:15 +0000
Subject: [PATCH 089/168] Bump flake8 from 5.0.4 to 6.0.0

Bumps [flake8](https://github.com/pycqa/flake8) from 5.0.4 to 6.0.0.
- [Release notes](https://github.com/pycqa/flake8/releases)
- [Commits](https://github.com/pycqa/flake8/compare/5.0.4...6.0.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index c3083bcb..93e37ffd 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
 black==22.10.0
-flake8==5.0.4
+flake8==6.0.0
 isort==5.10.1
 pydocstyle[toml]==6.1.1

From f9a176065d7d5f0b717d0bd73d9475434188b784 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 12 Dec 2022 05:02:22 +0000
Subject: [PATCH 090/168] Bump black from 22.10.0 to 22.12.0

Bumps [black](https://github.com/psf/black) from 22.10.0 to 22.12.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/22.10.0...22.12.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 93e37ffd..d38589e4 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
-black==22.10.0
+black==22.12.0
 flake8==6.0.0
 isort==5.10.1
 pydocstyle[toml]==6.1.1

From 8c2982e0e6ad4d9b5327ad92953a6b50ceeb04bb Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 13 Dec 2022 05:01:51 +0000
Subject: [PATCH 091/168] Bump isort from 5.10.1 to 5.11.1

Bumps [isort](https://github.com/pycqa/isort) from 5.10.1 to 5.11.1.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.10.1...5.11.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index d38589e4..48d55e88 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
-isort==5.10.1
+isort==5.11.1
 pydocstyle[toml]==6.1.1

From ba22aaf343c4477b43219121d39f4397d25d25ba Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 14 Dec 2022 05:02:32 +0000
Subject: [PATCH 092/168] Bump isort from 5.11.1 to 5.11.2

Bumps [isort](https://github.com/pycqa/isort) from 5.11.1 to 5.11.2.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.11.1...5.11.2)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 48d55e88..6b59e8f9 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
-isort==5.11.1
+isort==5.11.2
 pydocstyle[toml]==6.1.1

From 7bebbb2a16a08d2c148047bbe30313574f3ddba3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 22 Dec 2022 05:01:55 +0000
Subject: [PATCH 093/168] Bump isort from 5.11.2 to 5.11.4

Bumps [isort](https://github.com/pycqa/isort) from 5.11.2 to 5.11.4.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.11.2...5.11.4)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 6b59e8f9..f4fd0e44 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
-isort==5.11.2
+isort==5.11.4
 pydocstyle[toml]==6.1.1

From 2bdaed5af0b51ab52e6194c053d2a974bb755882 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 4 Jan 2023 05:02:08 +0000
Subject: [PATCH 094/168] Bump pydocstyle[toml] from 6.1.1 to 6.2.2

Bumps [pydocstyle[toml]](https://github.com/PyCQA/pydocstyle) from 6.1.1 to 6.2.2.
- [Release notes](https://github.com/PyCQA/pydocstyle/releases)
- [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/PyCQA/pydocstyle/compare/6.1.1...6.2.2)

---
updated-dependencies:
- dependency-name: pydocstyle[toml]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index f4fd0e44..6523f5c5 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -2,4 +2,4 @@ bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
 isort==5.11.4
-pydocstyle[toml]==6.1.1
+pydocstyle[toml]==6.2.2

From 0edddd5dd8a315d78b31433efd969d1904f052a9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 9 Jan 2023 05:02:53 +0000
Subject: [PATCH 095/168] Bump pydocstyle[toml] from 6.2.2 to 6.2.3

Bumps [pydocstyle[toml]](https://github.com/PyCQA/pydocstyle) from 6.2.2 to 6.2.3.
- [Release notes](https://github.com/PyCQA/pydocstyle/releases)
- [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/PyCQA/pydocstyle/compare/6.2.2...6.2.3)

---
updated-dependencies:
- dependency-name: pydocstyle[toml]
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 6523f5c5..b7697266 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -2,4 +2,4 @@ bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
 isort==5.11.4
-pydocstyle[toml]==6.2.2
+pydocstyle[toml]==6.2.3

From a2c4bd2bff3f0044d89ba6f274c6ff561406541d Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 18 Jan 2023 05:01:54 +0000
Subject: [PATCH 096/168] Bump pydocstyle[toml] from 6.2.3 to 6.3.0

Bumps [pydocstyle[toml]](https://github.com/PyCQA/pydocstyle) from 6.2.3 to 6.3.0.
- [Release notes](https://github.com/PyCQA/pydocstyle/releases)
- [Changelog](https://github.com/PyCQA/pydocstyle/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/PyCQA/pydocstyle/compare/6.2.3...6.3.0)

---
updated-dependencies:
- dependency-name: pydocstyle[toml]
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index b7697266..d59f7c60 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -2,4 +2,4 @@ bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
 isort==5.11.4
-pydocstyle[toml]==6.2.3
+pydocstyle[toml]==6.3.0

From 37e9f7fd8b0915982e122fdbd068874ee96a164a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 30 Jan 2023 05:02:49 +0000
Subject: [PATCH 097/168] Bump isort from 5.11.4 to 5.12.0

Bumps [isort](https://github.com/pycqa/isort) from 5.11.4 to 5.12.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.11.4...5.12.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index d59f7c60..6fec005b 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
 black==22.12.0
 flake8==6.0.0
-isort==5.11.4
+isort==5.12.0
 pydocstyle[toml]==6.3.0

From 3e1527f1122c4eaf106992e1814dd835e1c65c50 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 6 Feb 2023 16:02:26 +0100
Subject: [PATCH 098/168] Bump black from 22.12.0 to 23.1.0 (#202)

---
 example/example/migrations/0001_initial.py | 1 -
 linter-requirements.txt                    | 2 +-
 tests/test_forms.py                        | 4 +++-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/example/example/migrations/0001_initial.py b/example/example/migrations/0001_initial.py
index db45b1bb..a578fdce 100644
--- a/example/example/migrations/0001_initial.py
+++ b/example/example/migrations/0001_initial.py
@@ -6,7 +6,6 @@
 
 
 class Migration(migrations.Migration):
-
     initial = True
 
     dependencies = [
diff --git a/linter-requirements.txt b/linter-requirements.txt
index 6fec005b..649a6a1d 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.4
-black==22.12.0
+black==23.1.0
 flake8==6.0.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0
diff --git a/tests/test_forms.py b/tests/test_forms.py
index a3a0d8b5..c7ba75a1 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -269,7 +269,9 @@ def test_selected_option(self, db):
             in not_required_field.widget.render("primary_genre", 1)
             or '<option value="1" selected>One</option>'
             in not_required_field.widget.render("primary_genre", 1)
-        ), (not_required_field.widget.render("primary_genre", 1))
+        ), not_required_field.widget.render(
+            "primary_genre", 1
+        )
 
     def test_many_selected_option(self, db, genres):
         field = HeavySelect2MultipleWidgetForm().fields["genres"]

From 38ce1d62c150df5eb28fcd460f536ab283e51c4f Mon Sep 17 00:00:00 2001
From: Ivan Tham <pickfire@riseup.net>
Date: Wed, 8 Feb 2023 21:42:30 +0800
Subject: [PATCH 099/168] Add list support for static asset settings (#189)

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 django_select2/conf.py  | 12 ++++++------
 django_select2/forms.py |  4 +++-
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/django_select2/conf.py b/django_select2/conf.py
index 0f34f774..a704eb17 100644
--- a/django_select2/conf.py
+++ b/django_select2/conf.py
@@ -55,32 +55,32 @@ class Select2Conf(AppConf):
     It has set `select2_` as a default value, which you can change if needed.
     """
 
-    JS = "admin/js/vendor/select2/select2.full.min.js"
+    JS = ["admin/js/vendor/select2/select2.full.min.js"]
     """
     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::
 
-        SELECT2_JS = 'assets/js/select2.min.js'
+        SELECT2_JS = ['assets/js/select2.min.js']
 
     If you provide your own JS and would not like Django-Select2 to load any, change
     this setting to a blank string like so::
 
-        SELECT2_JS = ''
+        SELECT2_JS = []
 
     .. tip:: Change this setting to a local asset in your development environment to
         develop without an Internet connection.
     """
 
-    CSS = "admin/css/vendor/select2/select2.min.css"
+    CSS = ["admin/css/vendor/select2/select2.min.css"]
     """
     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::
 
-        SELECT2_CSS = 'assets/css/select2.css'
+        SELECT2_CSS = ['assets/css/select2.css']
 
     If you want to add more css (usually used in select2 themes), add a line
     in settings.py like this::
@@ -93,7 +93,7 @@ class Select2Conf(AppConf):
     If you provide your own CSS and would not like Django-Select2 to load any, change
     this setting to a blank string like so::
 
-        SELECT2_CSS = ''
+        SELECT2_CSS = []
 
     .. tip:: Change this setting to a local asset in your development environment to
         develop without an Internet connection.
diff --git a/django_select2/forms.py b/django_select2/forms.py
index da7b5e0d..eaea7743 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -127,9 +127,11 @@ def media(self):
         .. Note:: For more information visit
             https://docs.djangoproject.com/en/stable/topics/forms/media/#media-as-a-dynamic-property
         """
-        select2_js = [settings.SELECT2_JS] if settings.SELECT2_JS else []
+        select2_js = settings.SELECT2_JS if settings.SELECT2_JS else []
         select2_css = settings.SELECT2_CSS if settings.SELECT2_CSS else []
 
+        if isinstance(select2_js, str):
+            select2_js = [select2_js]
         if isinstance(select2_css, str):
             select2_css = [select2_css]
 

From 0681174acabfd30e1baf2cc0d99d9f0a116e2a5a Mon Sep 17 00:00:00 2001
From: Cleiton de Lima <CleitonDeLima@users.noreply.github.com>
Date: Wed, 8 Feb 2023 10:45:22 -0300
Subject: [PATCH 100/168] Support data_view and data_url class attributes on
 HeavySelect (#182)

---
 django_select2/forms.py |  6 ++++--
 tests/testapp/forms.py  | 14 ++++++++++----
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index eaea7743..045693e1 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -229,6 +229,8 @@ class HeavySelect2Mixin:
     """Mixin that adds select2's AJAX options and registers itself on Django's cache."""
 
     dependent_fields = {}
+    data_view = None
+    data_url = None
 
     def __init__(self, attrs=None, choices=(), **kwargs):
         """
@@ -249,8 +251,8 @@ def __init__(self, attrs=None, choices=(), **kwargs):
 
         self.uuid = str(uuid.uuid4())
         self.field_id = signing.dumps(self.uuid)
-        self.data_view = kwargs.pop("data_view", None)
-        self.data_url = kwargs.pop("data_url", None)
+        self.data_view = kwargs.pop("data_view", self.data_view)
+        self.data_url = kwargs.pop("data_url", self.data_url)
 
         dependent_fields = kwargs.pop("dependent_fields", None)
         if dependent_fields is not None:
diff --git a/tests/testapp/forms.py b/tests/testapp/forms.py
index da9487c5..ed90f222 100644
--- a/tests/testapp/forms.py
+++ b/tests/testapp/forms.py
@@ -51,6 +51,14 @@ def label_from_instance(self, obj):
         return force_str(obj.title).upper()
 
 
+class ArtistDataViewWidget(HeavySelect2Widget):
+    data_view = "heavy_data_1"
+
+
+class PrimaryGenreDataUrlWidget(HeavySelect2Widget):
+    data_url = "/heavy_data_2/"
+
+
 class AlbumSelect2WidgetForm(forms.ModelForm):
     class Meta:
         model = models.Album
@@ -143,11 +151,9 @@ class Select2WidgetForm(forms.Form):
 
 
 class HeavySelect2WidgetForm(forms.Form):
-    artist = forms.ChoiceField(
-        widget=HeavySelect2Widget(data_view="heavy_data_1"), choices=NUMBER_CHOICES
-    )
+    artist = forms.ChoiceField(widget=ArtistDataViewWidget(), choices=NUMBER_CHOICES)
     primary_genre = forms.ChoiceField(
-        widget=HeavySelect2Widget(data_view="heavy_data_2"),
+        widget=PrimaryGenreDataUrlWidget(),
         required=False,
         choices=NUMBER_CHOICES,
     )

From 81c9b254c78d3da9523e4c9e756b9231304737bb Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Wed, 8 Feb 2023 15:02:34 +0100
Subject: [PATCH 101/168] Fix #188 -- Add graphviz to RTD config

---
 .readthedocs.yaml | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.readthedocs.yaml b/.readthedocs.yaml
index 4fa27769..9b618d15 100644
--- a/.readthedocs.yaml
+++ b/.readthedocs.yaml
@@ -6,6 +6,8 @@ version: 2
 
 build:
   os: ubuntu-20.04
+  apt_packages:
+    - graphviz
   tools:
     python: "3.10"
 

From f29cb40ca47e23c1c649e8abfa8ac0396c35c4cd Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 10 Mar 2023 05:57:28 +0000
Subject: [PATCH 102/168] Bump bandit from 1.7.4 to 1.7.5

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.4 to 1.7.5.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.4...1.7.5)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 649a6a1d..fc6e8bc5 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.4
+bandit==1.7.5
 black==23.1.0
 flake8==6.0.0
 isort==5.12.0

From d307c317799e9e9348fcf98974a4fea95e31b387 Mon Sep 17 00:00:00 2001
From: Joachim Jablon <joachim@botify.com>
Date: Mon, 6 Feb 2023 14:28:48 +0100
Subject: [PATCH 103/168] Fix override_settings issue

---
 django_select2/apps.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/django_select2/apps.py b/django_select2/apps.py
index 921269b6..98905972 100644
--- a/django_select2/apps.py
+++ b/django_select2/apps.py
@@ -7,3 +7,6 @@ class Select2AppConfig(AppConfig):
 
     name = "django_select2"
     verbose_name = "Select2"
+
+    def ready(self):
+        from . import conf

From 1fb55d6cd24454bcf5f35fe7815d10dc1c92b1d4 Mon Sep 17 00:00:00 2001
From: Joachim Jablon <ewjoachim@gmail.com>
Date: Sat, 11 Feb 2023 17:25:24 +0100
Subject: [PATCH 104/168] Update django_select2/apps.py

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 django_select2/apps.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_select2/apps.py b/django_select2/apps.py
index 98905972..052473a5 100644
--- a/django_select2/apps.py
+++ b/django_select2/apps.py
@@ -9,4 +9,4 @@ class Select2AppConfig(AppConfig):
     verbose_name = "Select2"
 
     def ready(self):
-        from . import conf
+        from . import conf. # noqa

From f9a439d7f40b8a17e87f5c820e10825caca81ae7 Mon Sep 17 00:00:00 2001
From: Joachim Jablon <ewjoachim@gmail.com>
Date: Sat, 11 Feb 2023 18:43:55 +0100
Subject: [PATCH 105/168] Fix extraneous dot

---
 django_select2/apps.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_select2/apps.py b/django_select2/apps.py
index 052473a5..77b053ac 100644
--- a/django_select2/apps.py
+++ b/django_select2/apps.py
@@ -9,4 +9,4 @@ class Select2AppConfig(AppConfig):
     verbose_name = "Select2"
 
     def ready(self):
-        from . import conf. # noqa
+        from . import conf  # noqa

From ebf5f766694b98bf614c96a99b6204652efd25ff Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 29 Mar 2023 05:57:34 +0000
Subject: [PATCH 106/168] Bump black from 23.1.0 to 23.3.0

Bumps [black](https://github.com/psf/black) from 23.1.0 to 23.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.1.0...23.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index fc6e8bc5..3523059f 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
-black==23.1.0
+black==23.3.0
 flake8==6.0.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From 0dc2e77f4ea4ce0acff515e95f3eef533bd09eb7 Mon Sep 17 00:00:00 2001
From: David Neugebauer <david.neugebauer@posteo.de>
Date: Fri, 5 May 2023 15:48:18 +0200
Subject: [PATCH 107/168] Fix #128, add documentation on how to confifure
 select2 options

---
 docs/django_select2.rst | 42 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 38 insertions(+), 4 deletions(-)

diff --git a/docs/django_select2.rst b/docs/django_select2.rst
index b726099a..512739b1 100644
--- a/docs/django_select2.rst
+++ b/docs/django_select2.rst
@@ -55,13 +55,47 @@ plugin.  It will handle both normal and heavy fields. Simply call
 
         $('.django-select2').djangoSelect2();
 
+Please replace all your ``.select2`` invocations with the here provided
+``.djangoSelect2``.
 
-You can pass see `Select2 options <https://select2.github.io/options.html>`_ if needed::
 
-        $('.django-select2').djangoSelect2({placeholder: 'Select an option'});
+Configuring Select2
+-------------------
+
+Select2 options can be configured either directly from Javascript or from within Django
+using widget attributes. `(List of options in the Select2 docs) <https://select2.org/configuration/options-api>`_.
+
+To pass options in javascript
+
+.. code-block:: javascript
+
+    $('.django-select2').djangoSelect2({
+        minimumInputLength: 0,
+        placeholder: 'Select an option',
+    });
+
+From Django, you can use ``data-`` attributes using the same names in camel-case and
+passing them to your widget. Select2 will then pick these up. For example when
+initialising a widget in a form, you could do:
+
+.. code-block:: python
+
+    class MyForm(forms.Form):
+        my_field = forms.ModelMultipleChoiceField(
+            widget=ModelSelect2MultipleWidget(
+                model=MyModel
+                search_fields=['another_field']
+                attrs={
+                    "data-minimum-input-length": 0,
+                    "data-placeholder": "Select an option",
+                    "data-close-on-select": "false",
+                }
+            )
+        )
+
+(If you do not want to initialize the widget, you could add the attributes by overriding
+a widget method and adding them in a super call, e.g. `get_context() <https://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.get_context>`_)
 
-Please replace all your ``.select2`` invocations with the here provided
-``.djangoSelect2``.
 
 Security & Authentication
 -------------------------

From c3097428ae343d001cef7fd2b5d524f6af0e90f6 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 5 May 2023 17:34:25 +0200
Subject: [PATCH 108/168] Fix #214 -- Update contributing guilde

---
 CONTRIBUTING.rst | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index d3ccb2e0..edec7794 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -1,17 +1,27 @@
 Contributing
 ============
 
-This package uses the pyTest test runner. To run the tests locally simply run::
+Before you start editing the python code, you will need to make sure
+you have binary dependencies installed::
 
-    python setup.py test
+    # Debian
+    sudo apt install -y gettext graphviz google-chrome-stable
+    # macOS
+    brew install -y gettext graphviz google-chrome-stable
 
-If you need to the development dependencies installed of you local IDE, you can run::
+To install the package and its dependencies for development
+including tests dependencies, please do:
 
-    python setup.py develop
+    python -m pip install -e .[test]
+    
+You may ran the tests via::
+
+    python -m pytest
 
 Documentation pull requests welcome. The Sphinx documentation can be compiled via::
 
-    python setup.py build_sphinx
+    python -m pip install -e .[docs]
+    python -m sphinx -W -b doctest -b html docs docs/_build
 
 Bug reports welcome, even more so if they include a correct patch.  Much
 more so if you start your patch by adding a failing unit test, and correct

From f0e9555ad7e4095d821d33dc389ab0e4f42e8913 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Tue, 23 May 2023 15:45:55 +0200
Subject: [PATCH 109/168] Update Python & Django version support (#218)

* Add Django 4.2 support
* Drop Django 4.0 support
* Add Python 3.11 support
---
 .github/workflows/ci.yml | 3 ++-
 pyproject.toml           | 6 ++++--
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index bc44000f..e2e16142 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -69,10 +69,11 @@ jobs:
           - "3.8"
           - "3.9"
           - "3.10"
+          - "3.11"
         django-version:
           - "3.2"
-          - "4.0"
           - "4.1"
+          - "4.2"
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
diff --git a/pyproject.toml b/pyproject.toml
index 1d4fb2f5..d6ce5548 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,13 +20,14 @@ classifiers = [
   "Programming Language :: Python",
   "Programming Language :: Python :: 3",
   "Programming Language :: Python :: 3 :: Only",
-  "Programming Language :: Python :: 3.9",
+  "Programming Language :: Python :: 3.8",
   "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
+  "Programming Language :: Python :: 3.11",
   "Framework :: Django",
   "Framework :: Django :: 3.2",
-  "Framework :: Django :: 4.0",
   "Framework :: Django :: 4.1",
+  "Framework :: Django :: 4.2",
   "Topic :: Software Development",
 ]
 requires-python = ">=3.8"
@@ -67,6 +68,7 @@ minversion = "6.0"
 addopts = "--cov --tb=short -rxs"
 testpaths = ["tests"]
 DJANGO_SETTINGS_MODULE = "tests.testapp.settings"
+filterwarnings = ["ignore::PendingDeprecationWarning", "error::RuntimeWarning"]
 
 [tool.coverage.run]
 source = ["django_select2"]

From ed1af309908d1c8c94a189209b0a40479ee95320 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Romain=20S=C3=A9bille?=
 <20045330+rsebille@users.noreply.github.com>
Date: Tue, 23 May 2023 16:30:30 +0200
Subject: [PATCH 110/168] [Django 4.1+] Make i18n works for LANGUAGE_CODE with
 a country code (#206)

When using a `LANGUAGE_CODE` with a country code and a supported
language (_ie_: `fr-FR`) the current implementation of
`Select2Mixin.i18n_name` will return `None` which means default
_select2_ language, so English.


Co-authored-by: Johannes Maron <johannes@maron.family>
---
 CONTRIBUTING.rst        |  2 +-
 django_select2/forms.py | 15 ++++++---
 tests/test_forms.py     | 71 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 83 insertions(+), 5 deletions(-)

diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index edec7794..f4367f9c 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -13,7 +13,7 @@ To install the package and its dependencies for development
 including tests dependencies, please do:
 
     python -m pip install -e .[test]
-    
+
 You may ran the tests via::
 
     python -m pytest
diff --git a/django_select2/forms.py b/django_select2/forms.py
index 045693e1..1c0c7059 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -54,12 +54,11 @@
 
 import django
 from django import forms
-from django.contrib.admin.widgets import SELECT2_TRANSLATIONS, AutocompleteMixin
+from django.contrib.admin.widgets import AutocompleteMixin
 from django.core import signing
 from django.db.models import Q
 from django.forms.models import ModelChoiceIterator
 from django.urls import reverse
-from django.utils.translation import get_language
 
 from .cache import cache
 from .conf import settings
@@ -89,7 +88,15 @@ class Select2Mixin:
     @property
     def i18n_name(self):
         """Name of the i18n file for the current language."""
-        return SELECT2_TRANSLATIONS.get(get_language())
+        if django.VERSION < (4, 1):
+            from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
+            from django.utils.translation import get_language
+
+            return SELECT2_TRANSLATIONS.get(get_language())
+        else:
+            from django.contrib.admin.widgets import get_select2_language
+
+            return get_select2_language()
 
     def build_attrs(self, base_attrs, extra_attrs=None):
         """Add select2 data attributes."""
@@ -258,7 +265,7 @@ def __init__(self, attrs=None, choices=(), **kwargs):
         if dependent_fields is not None:
             self.dependent_fields = dict(dependent_fields)
         if not (self.data_view or self.data_url):
-            raise ValueError('You must ether specify "data_view" or "data_url".')
+            raise ValueError('You must either specify "data_view" or "data_url".')
         self.userGetValTextFuncName = kwargs.pop("userGetValTextFuncName", "null")
 
     def get_url(self):
diff --git a/tests/test_forms.py b/tests/test_forms.py
index c7ba75a1..c7281949 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -2,6 +2,7 @@
 import os
 from collections.abc import Iterable
 
+import django
 import pytest
 from django.db.models import QuerySet
 from django.urls import reverse
@@ -822,3 +823,73 @@ def test_dependent_fields_clear_after_change_parent(
             )
         )
         assert city2_container.text == ""
+
+
+@pytest.fixture(
+    name="widget",
+    params=[
+        (Select2Widget, {}),
+        (HeavySelect2Widget, {"data_view": "heavy_data_1"}),
+        (HeavySelect2MultipleWidget, {"data_view": "heavy_data_1"}),
+        (ModelSelect2Widget, {}),
+        (ModelSelect2TagWidget, {}),
+    ],
+    ids=lambda p: p[0],
+)
+def widget_fixture(request):
+    widget_class, widget_kwargs = request.param
+    return widget_class(**widget_kwargs)
+
+
+@pytest.mark.skipif(django.VERSION < (4, 1), reason="Only for Django 4.1+")
+@pytest.mark.parametrize(
+    "locale,expected",
+    [
+        ("fr-FR", "fr"),
+        # Some locales with a country code are natively supported by select2's i18n
+        ("pt-BR", "pt-BR"),
+        ("sr-Cyrl", "sr-Cyrl"),
+    ],
+    ids=repr,
+)
+def test_i18n_name_property_with_country_code_in_locale(widget, locale, expected):
+    """Test we fall back to the language code if the locale contain an unsupported country code."""
+    with translation.override(locale):
+        assert widget.i18n_name == expected
+
+
+@pytest.mark.skipif(django.VERSION < (4, 1), reason="Only for Django 4.1+")
+def test_i18n_media_js_with_country_code_in_locale(widget):
+    translation.activate("fr-FR")
+    assert tuple(widget.media._js) == (
+        "admin/js/vendor/select2/select2.full.min.js",
+        "admin/js/vendor/select2/i18n/fr.js",
+        "django_select2/django_select2.js",
+    )
+
+
+@pytest.mark.skipif(django.VERSION >= (4, 1), reason="Only for Django 4.0 and previous")
+@pytest.mark.parametrize(
+    "locale,expected",
+    [
+        ("fr-FR", None),
+        # Some locales with a country code are natively supported by select2's i18n
+        ("pt-BR", "pt-BR"),
+        ("sr-Cyrl", "sr-Cyrl"),
+    ],
+)
+def test_i18n_name_property_with_country_code_in_locale_for_older_django(
+    widget, locale, expected
+):
+    """No fallback for locale with an unsupported country code."""
+    with translation.override(locale):
+        assert widget.i18n_name == expected
+
+
+@pytest.mark.skipif(django.VERSION >= (4, 1), reason="Only for Django 4.0 and previous")
+def test_i18n_media_js_with_country_code_in_locale_for_older_django(widget):
+    translation.activate("fr-FR")
+    assert tuple(widget.media._js) == (
+        "admin/js/vendor/select2/select2.full.min.js",
+        "django_select2/django_select2.js",
+    )

From a4bc3273038e563a0a74adbb01ad36177bdef039 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 11 Jul 2023 05:50:38 +0000
Subject: [PATCH 111/168] Bump black from 23.3.0 to 23.7.0

Bumps [black](https://github.com/psf/black) from 23.3.0 to 23.7.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.3.0...23.7.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 3523059f..8d64fa20 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
-black==23.3.0
+black==23.7.0
 flake8==6.0.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From 5753384b489c283b7b08f9f4346c80a5a735fbe6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 31 Jul 2023 05:29:45 +0000
Subject: [PATCH 112/168] Bump flake8 from 6.0.0 to 6.1.0

Bumps [flake8](https://github.com/pycqa/flake8) from 6.0.0 to 6.1.0.
- [Commits](https://github.com/pycqa/flake8/compare/6.0.0...6.1.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 8d64fa20..77d18507 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
 black==23.7.0
-flake8==6.0.0
+flake8==6.1.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From 681fac9ad7d64fe9991c60e9b33d4c85ad2637e6 Mon Sep 17 00:00:00 2001
From: Klaas van Schelven <klaas@vanschelven.com>
Date: Mon, 4 Sep 2023 19:17:47 +0200
Subject: [PATCH 113/168] Note case in which cache is not needed (#233)

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 django_select2/forms.py | 67 +++++++++++++++++++++++------------------
 docs/conf.py            |  1 +
 docs/index.rst          |  5 +--
 3 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 1c0c7059..96846038 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -7,36 +7,43 @@
 library, hence these components are meant to be used
 with choice fields.
 
-Widgets are generally of two types:
-
-    1. **Light** --
-    They are not meant to be used when there
-    are too many options, say, in thousands.
-    This is because all those options would
-    have to be pre-rendered onto the page
-    and JavaScript would be used to search
-    through them. Said that, they are also one
-    the easiest to use. They are a
-    drop-in-replacement for Django's default
-    select widgets.
-
-    2(a). **Heavy** --
-    They are suited for scenarios when the number of options
-    are large and need complex queries (from maybe different
-    sources) to get the options.
-
-    This dynamic fetching of options undoubtedly requires
-    Ajax communication with the server. Django-Select2 includes
-    a helper JS file which is included automatically,
-    so you need not worry about writing any Ajax related JS code.
-    Although on the server side you do need to create a view
-    specifically to respond to the queries.
-
-    2(b). **Model** --
-    Model-widgets are a further specialized versions of Heavies.
-    These do not require views to serve Ajax requests.
-    When they are instantiated, they register themselves
-    with one central view which handles Ajax requests for them.
+Widgets are generally of tree types:
+Light, Heavy and Model.
+
+Light
+~~~~~
+
+They are not meant to be used when there
+are too many options, say, in thousands.
+This is because all those options would
+have to be pre-rendered onto the page
+and JavaScript would be used to search
+through them. Said that, they are also one
+the easiest to use. They are a
+drop-in-replacement for Django's default
+select widgets.
+
+Heavy
+~~~~~
+
+They are suited for scenarios when the number of options
+are large and need complex queries (from maybe different
+sources) to get the options.
+
+This dynamic fetching of options undoubtedly requires
+Ajax communication with the server. Django-Select2 includes
+a helper JS file which is included automatically,
+so you need not worry about writing any Ajax related JS code.
+Although on the server side you do need to create a view
+specifically to respond to the queries.
+
+Model
+~~~~~
+
+Model-widgets are a further specialized versions of Heavies.
+These do not require views to serve Ajax requests.
+When they are instantiated, they register themselves
+with one central view which handles Ajax requests for them.
 
 Heavy and Model widgets have respectively the word 'Heavy' and 'Model' in
 their name.  Light widgets are normally named, i.e. there is no 'Light' word
diff --git a/docs/conf.py b/docs/conf.py
index b339972f..845ceecd 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -31,6 +31,7 @@
 
 extensions = [
     "sphinx.ext.autodoc",
+    "sphinx.ext.autosectionlabel",
     "sphinx.ext.napoleon",
     "sphinx.ext.inheritance_diagram",
     "sphinx.ext.intersphinx",
diff --git a/docs/index.rst b/docs/index.rst
index 35454f9c..0b2772ea 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -32,8 +32,9 @@ Add ``django_select`` to your URL root configuration:
     ]
 
 
-``django-select2`` requires a cache backend which is **persistent**
-across all application servers..
+The :ref:`Model` -widgets require a **persistent** cache backend across
+all application servers. This is because the widget needs to store
+meta data to be able to fetch the results based on the user input.
 
 **This means that the** :class:`.DummyCache` **backend will not work!**
 

From cb1142b31b77f271f6ff88a2c9ff7e22e53ad145 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 5 Sep 2023 05:17:18 +0000
Subject: [PATCH 114/168] Bump actions/checkout from 3 to 4

Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 12 ++++++------
 .github/workflows/release.yml |  4 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index e2e16142..18c9710e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,7 +18,7 @@ jobs:
           - isort --check-only --diff .
           - pydocstyle .
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"
@@ -30,7 +30,7 @@ jobs:
   dist:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"
@@ -41,7 +41,7 @@ jobs:
   standardjs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-node@v3
         with:
           node-version: '12.x'
@@ -51,7 +51,7 @@ jobs:
   docs:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: "3.10"
@@ -76,7 +76,7 @@ jobs:
           - "4.2"
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: ${{ matrix.python-version }}
@@ -95,7 +95,7 @@ jobs:
           - "3.x"
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - name: Install Chrome
         run: sudo apt-get install -y google-chrome-stable
       - name: Install Selenium
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f6548af4..0d68a559 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,7 +8,7 @@ jobs:
   PyPI:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"
@@ -23,7 +23,7 @@ jobs:
   npm:
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
       - uses: actions/setup-node@v3
       - uses: actions/setup-python@v4
         with:

From 9b7eea49aedd2a97db09fbb5abc8f6b5dc2ad1d1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 11 Sep 2023 05:44:27 +0000
Subject: [PATCH 115/168] Bump black from 23.7.0 to 23.9.1

Bumps [black](https://github.com/psf/black) from 23.7.0 to 23.9.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.7.0...23.9.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 77d18507..d132dc97 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
-black==23.7.0
+black==23.9.1
 flake8==6.1.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From d0704c462c6dff71883ab85f81376172527a1867 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 15 Sep 2023 05:32:08 +0000
Subject: [PATCH 116/168] Bump codecov/codecov-action from 3 to 4

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 18c9710e..b754d4de 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -83,7 +83,7 @@ jobs:
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
       - run: python -m pip install -e .[test]
       - run: python -m pytest -m "not selenium"
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v4
 
   Selenium:
     needs:
@@ -109,4 +109,4 @@ jobs:
       - run: python -m pip install Django
       - run: python -m pip install -e .[test,selenium]
       - run: python -m pytest -m selenium
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v4

From 2cd60943c5076c2e78d64d5d70771a370b9e22b6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 18 Oct 2023 05:07:26 +0000
Subject: [PATCH 117/168] Bump black from 23.9.1 to 23.10.0

Bumps [black](https://github.com/psf/black) from 23.9.1 to 23.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.9.1...23.10.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index d132dc97..2f7cbf58 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
-black==23.9.1
+black==23.10.0
 flake8==6.1.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From 85fba6b8a40bc66a75bc57b2a509be24ae28c2d0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 24 Oct 2023 05:49:28 +0000
Subject: [PATCH 118/168] Bump black from 23.10.0 to 23.10.1

Bumps [black](https://github.com/psf/black) from 23.10.0 to 23.10.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.0...23.10.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 2f7cbf58..3ff65113 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
-black==23.10.0
+black==23.10.1
 flake8==6.1.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From 2ec738949411ae845ebb16ae306d8e282ca2b4f5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 24 Oct 2023 05:47:45 +0000
Subject: [PATCH 119/168] Bump actions/setup-node from 3 to 4

Bumps [actions/setup-node](https://github.com/actions/setup-node) from 3 to 4.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](https://github.com/actions/setup-node/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 2 +-
 .github/workflows/release.yml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b754d4de..4b238cee 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,7 +42,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-node@v3
+      - uses: actions/setup-node@v4
         with:
           node-version: '12.x'
       - run: npm install -g standard
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 0d68a559..3eb0a40b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -24,7 +24,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-node@v3
+      - uses: actions/setup-node@v4
       - uses: actions/setup-python@v4
         with:
           python-version: "3.x"

From 69eef256d8c2a47ca6e13b370e8ed79fdac3093d Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 27 Oct 2023 16:56:45 +0200
Subject: [PATCH 120/168] Revert "Bump codecov/codecov-action from 3 to 4"

This reverts commit d0704c462c6dff71883ab85f81376172527a1867.
---
 .github/workflows/ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4b238cee..5d959da7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -83,7 +83,7 @@ jobs:
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
       - run: python -m pip install -e .[test]
       - run: python -m pytest -m "not selenium"
-      - uses: codecov/codecov-action@v4
+      - uses: codecov/codecov-action@v3
 
   Selenium:
     needs:
@@ -109,4 +109,4 @@ jobs:
       - run: python -m pip install Django
       - run: python -m pip install -e .[test,selenium]
       - run: python -m pytest -m selenium
-      - uses: codecov/codecov-action@v4
+      - uses: codecov/codecov-action@v3

From 05ec6c551f9d0915ddaf4604b8ae5824c769c53b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 9 Nov 2023 05:04:01 +0000
Subject: [PATCH 121/168] Bump black from 23.10.1 to 23.11.0

Bumps [black](https://github.com/psf/black) from 23.10.1 to 23.11.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.10.1...23.11.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 3ff65113..56e8bc79 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.5
-black==23.10.1
+black==23.11.0
 flake8==6.1.0
 isort==5.12.0
 pydocstyle[toml]==6.3.0

From 29f2908b549fba96292a6af8d8dbb7fa136e1327 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 24 Nov 2023 13:40:23 +0100
Subject: [PATCH 122/168] Update issue tempaltes

---
 .github/ISSUE_TEMPLATE/bug.yml                | 52 +++++++++++++++++++
 .github/ISSUE_TEMPLATE/bug_report.md          | 30 -----------
 .github/ISSUE_TEMPLATE/feature.yml            | 11 ++++
 .github/ISSUE_TEMPLATE/feature_request.md     | 20 -------
 .../problem-with-django-admin.md              | 13 -----
 .github/ISSUE_TEMPLATE/question.md            | 17 ------
 .github/ISSUE_TEMPLATE/question.yml           | 11 ++++
 7 files changed, 74 insertions(+), 80 deletions(-)
 create mode 100644 .github/ISSUE_TEMPLATE/bug.yml
 delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md
 create mode 100644 .github/ISSUE_TEMPLATE/feature.yml
 delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
 delete mode 100644 .github/ISSUE_TEMPLATE/problem-with-django-admin.md
 delete mode 100644 .github/ISSUE_TEMPLATE/question.md
 create mode 100644 .github/ISSUE_TEMPLATE/question.yml

diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml
new file mode 100644
index 00000000..66e8eda0
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug.yml
@@ -0,0 +1,52 @@
+name: 🐛 Bug
+description: Report a technical issue.
+title: '🐛 '
+labels:
+  - bug
+assignees:
+  - codingjoe
+body:
+
+  - type: markdown
+    attributes:
+      value: |
+        Thank you for taking the time to report a bug.
+        Please fill in as much of the template below as you're able.
+
+  - type: markdown
+    attributes:
+      value: |
+        ## Security issues
+        Please do not report security issues here.
+        Instead, disclose them as described in our [security policy](https://github.com/codingjoe/django-select2/security).
+
+  - type: textarea
+    id: bug-description
+    attributes:
+      label: Bug Description
+      description: A clear and concise description of what the bug is.
+      placeholder: I found a bug
+    validations:
+      required: true
+
+  - type: textarea
+    id: bug-steps
+    attributes:
+      label: Steps to Reproduce
+      description: Steps to reproduce the behavior.
+      placeholder: |
+        1. Go to '...'
+        2. Click on '....'
+        3. Scroll down to '....'
+        4. See error
+    validations:
+      required: true
+
+  - type: textarea
+    id: bug-expected
+    attributes:
+      label: Expected Behavior
+      description: A clear and concise description of what you expected to happen.
+      placeholder: I expected the app to do X
+    validations:
+      required: true
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 61090361..00000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,30 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: bug
-assignees: codingjoe
-
----
-
-**Describe the bug**
-A clear and concise description of what the bug is.
-
-**Exception & Traceback**
-Should you have run into an exception, please provide us with the exception as well as with the full traceback.
-
-**Code Snippet**
-Please provide us with a code example on how to reproduce the error.
-
-**To Reproduce**
-Steps to reproduce the behavior:
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
-
-**Expected behavior**
-A clear and concise description of what you expected to happen.
-
-**Screenshots**
-If applicable, add screenshots to help explain your problem.
diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml
new file mode 100644
index 00000000..98acba30
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature.yml
@@ -0,0 +1,11 @@
+name: ✨ Feature
+description: Request an enhancement.
+body:
+
+  - type: markdown
+    attributes:
+      value: |
+        ## Discussions
+
+        This project uses GitHub Discussions for feature requests.
+        Please use the [Ideas Section](https://github.com/codingjoe/django-select2/discussions/categories/ideas) to discuss your idea with the community.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index bbcbbe7d..00000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project
-title: ''
-labels: ''
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/ISSUE_TEMPLATE/problem-with-django-admin.md b/.github/ISSUE_TEMPLATE/problem-with-django-admin.md
deleted file mode 100644
index ce54f92c..00000000
--- a/.github/ISSUE_TEMPLATE/problem-with-django-admin.md
+++ /dev/null
@@ -1,13 +0,0 @@
----
-name: Problem with Django admin
-about: You are facing a problem integrating django-select2 into Django's admin interface
-title: ''
-labels: wontfix
-assignees: ''
-
----
-
-Django-Select2 does NOT support Django admin, since Django admin has a built-in feature called `autocomplete_fields`. Autocomplete fields are superior and we recommend using them, instead of this package for the admin.
-
-You can find more information here:
-https://docs.djangoproject.com/en/stable/ref/contrib/admin/#django.contrib.admin.ModelAdmin.autocomplete_fields
diff --git a/.github/ISSUE_TEMPLATE/question.md b/.github/ISSUE_TEMPLATE/question.md
deleted file mode 100644
index ae936a5e..00000000
--- a/.github/ISSUE_TEMPLATE/question.md
+++ /dev/null
@@ -1,17 +0,0 @@
----
-name: Question
-about: You have a question about Django-Select2
-title: ''
-labels: question
-assignees: ''
-
----
-
-**Goal**
-Please describe your goal in all detail. What are you trying to do
-
-**Problem**
-Please describe your problem in all detail. Where are you struggling?
-
-**Code Snippet**
-Please provide a code snippet of your problem.
diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml
new file mode 100644
index 00000000..413ed544
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/question.yml
@@ -0,0 +1,11 @@
+name: 🙋 Question
+description: Get help from the community.
+body:
+
+  - type: markdown
+    attributes:
+      value: |
+        ## Discussions
+
+        This project uses GitHub Discussions to answer your questions.
+        Please use the [Q&A](https://github.com/codingjoe/django-select2/discussions/categories/q-a) to discuss your idea with the community.

From 3532dce016ed2e75e71d2b0096cf4146e39e6f4a Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 24 Nov 2023 13:47:00 +0100
Subject: [PATCH 123/168] Add a issues config file

---
 .github/ISSUE_TEMPLATE/config.yml   | 11 +++++++++++
 .github/ISSUE_TEMPLATE/feature.yml  | 11 -----------
 .github/ISSUE_TEMPLATE/question.yml | 11 -----------
 3 files changed, 11 insertions(+), 22 deletions(-)
 create mode 100644 .github/ISSUE_TEMPLATE/config.yml
 delete mode 100644 .github/ISSUE_TEMPLATE/feature.yml
 delete mode 100644 .github/ISSUE_TEMPLATE/question.yml

diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 00000000..2fc862f5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,11 @@
+blank_issues_enabled: false
+contact_links:
+  - name: Security Policy
+    url: https://github.com/codingjoe/django-select2/security
+    about: Please do not disclose security vulnerabilities via GitHub issues.
+  - name: ✨ Feature Requests
+    url: https://github.com/codingjoe/django-select2/discussions/categories/ideas
+    about: Please use the GitHub Discussions to request new features.
+  - name: 🙋 Questions & Help
+    url: https://github.com/codingjoe/django-select2/discussions/categories/q-a
+    about: Please use the GitHub Discussions to ask questions.
diff --git a/.github/ISSUE_TEMPLATE/feature.yml b/.github/ISSUE_TEMPLATE/feature.yml
deleted file mode 100644
index 98acba30..00000000
--- a/.github/ISSUE_TEMPLATE/feature.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-name: ✨ Feature
-description: Request an enhancement.
-body:
-
-  - type: markdown
-    attributes:
-      value: |
-        ## Discussions
-
-        This project uses GitHub Discussions for feature requests.
-        Please use the [Ideas Section](https://github.com/codingjoe/django-select2/discussions/categories/ideas) to discuss your idea with the community.
diff --git a/.github/ISSUE_TEMPLATE/question.yml b/.github/ISSUE_TEMPLATE/question.yml
deleted file mode 100644
index 413ed544..00000000
--- a/.github/ISSUE_TEMPLATE/question.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-name: 🙋 Question
-description: Get help from the community.
-body:
-
-  - type: markdown
-    attributes:
-      value: |
-        ## Discussions
-
-        This project uses GitHub Discussions to answer your questions.
-        Please use the [Q&A](https://github.com/codingjoe/django-select2/discussions/categories/q-a) to discuss your idea with the community.

From 69dd8921781e1771f54ad10733d5e1beff6e7043 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Fri, 24 Nov 2023 13:48:35 +0100
Subject: [PATCH 124/168] Drop secuirty link in favor of CVE

---
 .github/ISSUE_TEMPLATE/config.yml | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 2fc862f5..68d01326 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,8 +1,5 @@
 blank_issues_enabled: false
 contact_links:
-  - name: Security Policy
-    url: https://github.com/codingjoe/django-select2/security
-    about: Please do not disclose security vulnerabilities via GitHub issues.
   - name: ✨ Feature Requests
     url: https://github.com/codingjoe/django-select2/discussions/categories/ideas
     about: Please use the GitHub Discussions to request new features.

From c458e3e332eb247c1a9042019cccab2a9a5af00c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 11 Dec 2023 05:07:47 +0000
Subject: [PATCH 125/168] Bump bandit from 1.7.5 to 1.7.6

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.5 to 1.7.6.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.5...1.7.6)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 56e8bc79..dbcba5e9 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.5
+bandit==1.7.6
 black==23.11.0
 flake8==6.1.0
 isort==5.12.0

From 47ecddc639c28489d868e425187ef7bde389c927 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 11 Dec 2023 08:54:06 +0000
Subject: [PATCH 126/168] Bump isort from 5.12.0 to 5.13.0

Bumps [isort](https://github.com/pycqa/isort) from 5.12.0 to 5.13.0.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.12.0...5.13.0)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index dbcba5e9..91a398c8 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.6
 black==23.11.0
 flake8==6.1.0
-isort==5.12.0
+isort==5.13.0
 pydocstyle[toml]==6.3.0

From a88987de4fb19ccb4d57e751f3dddbf75256a2f1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 7 Dec 2023 05:02:28 +0000
Subject: [PATCH 127/168] Bump actions/setup-python from 4 to 5

Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml      | 10 +++++-----
 .github/workflows/release.yml |  4 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 5d959da7..766f40f5 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -19,7 +19,7 @@ jobs:
           - pydocstyle .
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.x"
           cache: 'pip'
@@ -31,7 +31,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.x"
       - run: python -m pip install --upgrade pip build wheel twine readme-renderer
@@ -52,7 +52,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.10"
       - run: sudo apt-get install -y gettext graphviz
@@ -77,7 +77,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
@@ -103,7 +103,7 @@ jobs:
           mkdir bin
           curl -O https://chromedriver.storage.googleapis.com/`curl -s https://chromedriver.storage.googleapis.com/LATEST_RELEASE`/chromedriver_linux64.zip
           unzip chromedriver_linux64.zip -d bin
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: ${{ matrix.python-version }}
       - run: python -m pip install Django
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3eb0a40b..29ff0b81 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -9,7 +9,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.x"
       - run: python -m pip install --upgrade pip build wheel twine
@@ -25,7 +25,7 @@ jobs:
     steps:
       - uses: actions/checkout@v4
       - uses: actions/setup-node@v4
-      - uses: actions/setup-python@v4
+      - uses: actions/setup-python@v5
         with:
           python-version: "3.x"
       - run: python -m pip install --upgrade setuptools_scm

From 9e2a14e8c6d40add1f4db67be5790a4126499897 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 12 Dec 2023 05:33:47 +0000
Subject: [PATCH 128/168] Bump isort from 5.13.0 to 5.13.1

Bumps [isort](https://github.com/pycqa/isort) from 5.13.0 to 5.13.1.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.13.0...5.13.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 91a398c8..2a8b219e 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.6
 black==23.11.0
 flake8==6.1.0
-isort==5.13.0
+isort==5.13.1
 pydocstyle[toml]==6.3.0

From 94b9cc391018886cf02e3b3692565a5c24f698d9 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 13 Dec 2023 05:49:53 +0000
Subject: [PATCH 129/168] Bump black from 23.11.0 to 23.12.0

Bumps [black](https://github.com/psf/black) from 23.11.0 to 23.12.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.11.0...23.12.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 2a8b219e..67d627d2 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.6
-black==23.11.0
+black==23.12.0
 flake8==6.1.0
 isort==5.13.1
 pydocstyle[toml]==6.3.0

From 38927504572f301c9f717e15b9f1900fffedeb95 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 14 Dec 2023 06:00:13 +0000
Subject: [PATCH 130/168] Bump isort from 5.13.1 to 5.13.2

Bumps [isort](https://github.com/pycqa/isort) from 5.13.1 to 5.13.2.
- [Release notes](https://github.com/pycqa/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pycqa/isort/compare/5.13.1...5.13.2)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 67d627d2..06e16b83 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.6
 black==23.12.0
 flake8==6.1.0
-isort==5.13.1
+isort==5.13.2
 pydocstyle[toml]==6.3.0

From d1a3d51188081b3457c0abb00ba4e62c438210b2 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 25 Dec 2023 05:43:37 +0000
Subject: [PATCH 131/168] Bump black from 23.12.0 to 23.12.1

Bumps [black](https://github.com/psf/black) from 23.12.0 to 23.12.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.12.0...23.12.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 06e16b83..68fe48ea 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.6
-black==23.12.0
+black==23.12.1
 flake8==6.1.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From dc12b38cea32a2bc5b4bd1f093ce7b23fa115c1a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 5 Jan 2024 05:03:59 +0000
Subject: [PATCH 132/168] Bump flake8 from 6.1.0 to 7.0.0

Bumps [flake8](https://github.com/pycqa/flake8) from 6.1.0 to 7.0.0.
- [Commits](https://github.com/pycqa/flake8/compare/6.1.0...7.0.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 68fe48ea..c0482d19 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.6
 black==23.12.1
-flake8==6.1.0
+flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From f61b09c6dabcb26d7311ddd69671900454328f97 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 24 Jan 2024 05:36:43 +0000
Subject: [PATCH 133/168] Bump bandit from 1.7.6 to 1.7.7

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.6 to 1.7.7.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.6...1.7.7)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index c0482d19..c262708e 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.6
+bandit==1.7.7
 black==23.12.1
 flake8==7.0.0
 isort==5.13.2

From ec2464507547d0c6fa0f1632469e670facd0c13c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 26 Jan 2024 05:57:05 +0000
Subject: [PATCH 134/168] Bump black from 23.12.1 to 24.1.0

Bumps [black](https://github.com/psf/black) from 23.12.1 to 24.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/23.12.1...24.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index c262708e..dd19df68 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.7
-black==23.12.1
+black==24.1.0
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 15e2d855d50de503b6c6941e2e5581260fa8f6f1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 1 Feb 2024 05:59:33 +0000
Subject: [PATCH 135/168] Bump codecov/codecov-action from 3 to 4

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 3 to 4.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 766f40f5..0a3c1aa7 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -83,7 +83,7 @@ jobs:
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
       - run: python -m pip install -e .[test]
       - run: python -m pytest -m "not selenium"
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v4
 
   Selenium:
     needs:
@@ -109,4 +109,4 @@ jobs:
       - run: python -m pip install Django
       - run: python -m pip install -e .[test,selenium]
       - run: python -m pytest -m selenium
-      - uses: codecov/codecov-action@v3
+      - uses: codecov/codecov-action@v4

From 21f30eaffd9b9500a0ee41c0a0d405f5182b6889 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Sun, 11 Feb 2024 13:41:00 +0100
Subject: [PATCH 136/168] Bump black from 24.1.0 to 24.1.1 (#264)

---
 django_select2/__init__.py | 1 +
 django_select2/apps.py     | 1 +
 django_select2/cache.py    | 1 +
 django_select2/conf.py     | 1 +
 django_select2/forms.py    | 1 +
 django_select2/urls.py     | 1 +
 django_select2/views.py    | 1 +
 linter-requirements.txt    | 2 +-
 8 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/django_select2/__init__.py b/django_select2/__init__.py
index 95783ce7..4966ddc6 100644
--- a/django_select2/__init__.py
+++ b/django_select2/__init__.py
@@ -7,6 +7,7 @@
 .. _Select2: https://select2.org/
 
 """
+
 from django import get_version
 
 from . import _version
diff --git a/django_select2/apps.py b/django_select2/apps.py
index 77b053ac..cc7d0b26 100644
--- a/django_select2/apps.py
+++ b/django_select2/apps.py
@@ -1,4 +1,5 @@
 """Django application configuration."""
+
 from django.apps import AppConfig
 
 
diff --git a/django_select2/cache.py b/django_select2/cache.py
index ce8953d0..6dbac226 100644
--- a/django_select2/cache.py
+++ b/django_select2/cache.py
@@ -11,6 +11,7 @@
 
 .. _django.core.cache: https://docs.djangoproject.com/en/dev/topics/cache/
 """
+
 from django.core.cache import caches
 
 from .conf import settings
diff --git a/django_select2/conf.py b/django_select2/conf.py
index a704eb17..e66b55d9 100644
--- a/django_select2/conf.py
+++ b/django_select2/conf.py
@@ -1,4 +1,5 @@
 """Settings for Django-Select2."""
+
 from appconf import AppConf
 from django.conf import settings  # NOQA
 
diff --git a/django_select2/forms.py b/django_select2/forms.py
index 96846038..bf9026a8 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -53,6 +53,7 @@
     :parts: 1
 
 """
+
 import operator
 import uuid
 from functools import reduce
diff --git a/django_select2/urls.py b/django_select2/urls.py
index 69c0f148..9f40776d 100644
--- a/django_select2/urls.py
+++ b/django_select2/urls.py
@@ -9,6 +9,7 @@
     path('select2/', include('django_select2.urls')),
 
 """
+
 from django.urls import path
 
 from .views import AutoResponseView
diff --git a/django_select2/views.py b/django_select2/views.py
index 66fdc420..64bff43e 100644
--- a/django_select2/views.py
+++ b/django_select2/views.py
@@ -1,4 +1,5 @@
 """JSONResponse views for model widgets."""
+
 from django.core import signing
 from django.core.signing import BadSignature
 from django.http import Http404, JsonResponse
diff --git a/linter-requirements.txt b/linter-requirements.txt
index dd19df68..b25090e7 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.7
-black==24.1.0
+black==24.1.1
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From d044bd851fa00af977e38c6d27b8cd5f0a28c186 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 13 Feb 2024 05:43:46 +0000
Subject: [PATCH 137/168] Bump black from 24.1.1 to 24.2.0

Bumps [black](https://github.com/psf/black) from 24.1.1 to 24.2.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.1.1...24.2.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index b25090e7..475dbf02 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.7
-black==24.1.1
+black==24.2.0
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 5e1ba196b664de4c616cb7cbd0e8c9ff44252054 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 11 Mar 2024 05:12:06 +0000
Subject: [PATCH 138/168] Bump bandit from 1.7.7 to 1.7.8

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.7 to 1.7.8.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.7...1.7.8)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 475dbf02..b5d36ad1 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.7
+bandit==1.7.8
 black==24.2.0
 flake8==7.0.0
 isort==5.13.2

From 73330182bdfd63d9fbe2acd68c6f9d8f1569bdfc Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 18 Mar 2024 05:36:07 +0000
Subject: [PATCH 139/168] Bump black from 24.2.0 to 24.3.0

Bumps [black](https://github.com/psf/black) from 24.2.0 to 24.3.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.2.0...24.3.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index b5d36ad1..a9c0ed04 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.8
-black==24.2.0
+black==24.3.0
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 5c70aff4a628a0c52179811ba08386ca2b82fe67 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 15 Apr 2024 05:31:57 +0000
Subject: [PATCH 140/168] Bump black from 24.3.0 to 24.4.0

Bumps [black](https://github.com/psf/black) from 24.3.0 to 24.4.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.3.0...24.4.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index a9c0ed04..25dd0f07 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.8
-black==24.3.0
+black==24.4.0
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 97dd17531e66ab0855be9fdf833050ce90727d35 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 25 Apr 2024 05:16:09 +0000
Subject: [PATCH 141/168] Bump black from 24.4.0 to 24.4.1

Bumps [black](https://github.com/psf/black) from 24.4.0 to 24.4.1.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.4.0...24.4.1)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 25dd0f07..11870526 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.8
-black==24.4.0
+black==24.4.1
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From f427b3113d47cf60ab524e9c32cbd336e01417c5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 26 Apr 2024 05:22:30 +0000
Subject: [PATCH 142/168] Bump black from 24.4.1 to 24.4.2

Bumps [black](https://github.com/psf/black) from 24.4.1 to 24.4.2.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.4.1...24.4.2)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 11870526..ce0fa00a 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.8
-black==24.4.1
+black==24.4.2
 flake8==7.0.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 2a2cefded6501dff9c6606ac0562c5d4c2f1f7e8 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Jun 2024 05:44:58 +0000
Subject: [PATCH 143/168] Bump flake8 from 7.0.0 to 7.1.0

Bumps [flake8](https://github.com/pycqa/flake8) from 7.0.0 to 7.1.0.
- [Commits](https://github.com/pycqa/flake8/compare/7.0.0...7.1.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index ce0fa00a..95557d3a 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.8
 black==24.4.2
-flake8==7.0.0
+flake8==7.1.0
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 06a437dde8651fc2320330369c04a2ba0315dd0c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Jun 2024 09:18:45 +0000
Subject: [PATCH 144/168] Bump bandit from 1.7.8 to 1.7.9

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.8 to 1.7.9.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.8...1.7.9)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 95557d3a..4b8d76cb 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.8
+bandit==1.7.9
 black==24.4.2
 flake8==7.1.0
 isort==5.13.2

From 07ea4b8cf996eb587fd3dacf4361bd579d83e8e2 Mon Sep 17 00:00:00 2001
From: Mark G <mark.gensler@protonmail.com>
Date: Sat, 29 Jun 2024 16:35:53 +0200
Subject: [PATCH 145/168] Add ModelSelect2Mixin.result_from_instance method
 (#272)

Enable users to easily override the result JSON per widget without implementing a separate view.

---------

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 django_select2/forms.py | 22 ++++++++++++++++++++++
 django_select2/views.py |  5 ++++-
 tests/test_forms.py     |  9 +++++++++
 tests/test_views.py     | 23 ++++++++++++++++++++++-
 tests/testapp/forms.py  | 14 ++++++++++++++
 5 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index bf9026a8..02860075 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -554,6 +554,28 @@ def label_from_instance(obj):
         """
         return str(obj)
 
+    def result_from_instance(self, obj, request):
+        """
+        Return a dictionary representing the object.
+
+        Can be overridden to change the result returned by
+        :class:`.AutoResponseView` for each object.
+
+        The request passed in will correspond to the request sent to the
+        :class:`.AutoResponseView` by the widget.
+
+        Example usage::
+
+            class MyWidget(ModelSelect2Widget):
+                def result_from_instance(obj, request):
+                    return {
+                        'id': obj.pk,
+                        'text': self.label_from_instance(obj),
+                        'extra_data': obj.extra_data,
+                    }
+        """
+        return {"id": obj.pk, "text": self.label_from_instance(obj)}
+
 
 class ModelSelect2Widget(ModelSelect2Mixin, HeavySelect2Widget):
     """
diff --git a/django_select2/views.py b/django_select2/views.py
index 64bff43e..f78f19ea 100644
--- a/django_select2/views.py
+++ b/django_select2/views.py
@@ -21,6 +21,9 @@ def get(self, request, *args, **kwargs):
         """
         Return a :class:`.django.http.JsonResponse`.
 
+        Each result will be rendered by the widget's
+        :func:`django_select2.forms.ModelSelect2Mixin.result_from_instance` method.
+
         Example::
 
             {
@@ -41,7 +44,7 @@ def get(self, request, *args, **kwargs):
         return JsonResponse(
             {
                 "results": [
-                    {"text": self.widget.label_from_instance(obj), "id": obj.pk}
+                    self.widget.result_from_instance(obj, request)
                     for obj in context["object_list"]
                 ],
                 "more": context["page_obj"].has_next(),
diff --git a/tests/test_forms.py b/tests/test_forms.py
index c7281949..ddb0f328 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -438,6 +438,15 @@ def test_get_queryset(self):
         widget.queryset = Genre.objects.all()
         assert isinstance(widget.get_queryset(), QuerySet)
 
+    def test_result_from_instance_ModelSelect2Widget(self, genres):
+        widget = ModelSelect2Widget()
+        widget.model = Genre
+        genre = Genre.objects.first()
+        assert widget.result_from_instance(genre, request=None) == {
+            "id": genre.pk,
+            "text": str(genre),
+        }
+
     def test_tag_attrs_Select2Widget(self):
         widget = Select2Widget()
         output = widget.render("name", "value")
diff --git a/tests/test_views.py b/tests/test_views.py
index e63ffe80..745dbfad 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -4,7 +4,11 @@
 
 from django_select2.cache import cache
 from django_select2.forms import ModelSelect2Widget
-from tests.testapp.forms import AlbumModelSelect2WidgetForm, ArtistCustomTitleWidget
+from tests.testapp.forms import (
+    AlbumModelSelect2WidgetForm,
+    ArtistCustomTitleWidget,
+    CityForm,
+)
 from tests.testapp.models import Genre
 
 try:
@@ -84,6 +88,23 @@ def test_label_from_instance(self, artists, client):
             "results"
         ]
 
+    def test_result_from_instance(self, cities, client):
+        url = reverse("django_select2:auto-json")
+
+        form = CityForm()
+        assert form.as_p()
+        field_id = form.fields["city"].widget.field_id
+        city = cities[0]
+        response = client.get(url, {"field_id": field_id, "term": city.name})
+        assert response.status_code == 200
+        data = json.loads(response.content.decode("utf-8"))
+        assert data["results"]
+        assert {
+            "id": city.pk,
+            "text": smart_str(city),
+            "country": smart_str(city.country),
+        } in data["results"]
+
     def test_url_check(self, client, artists):
         artist = artists[0]
         form = AlbumModelSelect2WidgetForm()
diff --git a/tests/testapp/forms.py b/tests/testapp/forms.py
index ed90f222..0b115339 100644
--- a/tests/testapp/forms.py
+++ b/tests/testapp/forms.py
@@ -232,3 +232,17 @@ class Meta:
         model = models.Groupie
         fields = "__all__"
         widgets = {"obsession": ArtistCustomTitleWidget}
+
+
+class CityModelSelect2Widget(ModelSelect2Widget):
+    model = City
+    search_fields = ["name"]
+
+    def result_from_instance(self, obj, request):
+        return {"id": obj.pk, "text": obj.name, "country": str(obj.country)}
+
+
+class CityForm(forms.Form):
+    city = forms.ModelChoiceField(
+        queryset=City.objects.all(), widget=CityModelSelect2Widget(), required=False
+    )

From abcd0f7f5aad6abc98157a57dee07d231b11586e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marduk=20Bola=C3=B1os?= <mardukbp@mac.com>
Date: Sun, 4 Aug 2024 11:37:42 +0200
Subject: [PATCH 146/168] Improve the documentation of Select2TagWidget (#291)

As already
[discussed](https://github.com/codingjoe/django-select2/discussions/290),
the documentation of this widget is lacking. This PR adds a description
of the functionality provided by the widget.
---
 django_select2/forms.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 02860075..69b1ee3c 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -221,7 +221,7 @@ class Select2MultipleWidget(Select2Mixin, forms.SelectMultiple):
 
 class Select2TagWidget(Select2TagMixin, Select2Mixin, forms.SelectMultiple):
     """
-    Select2 drop in widget for for tagging.
+    Select2 drop in widget with tagging support. It allows to dynamically create new options from text input by the user.
 
     Example for :class:`.django.contrib.postgres.fields.ArrayField`::
 

From 6f5561d3565a0d0de8f8aa54daa6c88d2790591e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 5 Aug 2024 05:32:28 +0000
Subject: [PATCH 147/168] Bump flake8 from 7.1.0 to 7.1.1

Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.0 to 7.1.1.
- [Commits](https://github.com/pycqa/flake8/compare/7.1.0...7.1.1)

---
updated-dependencies:
- dependency-name: flake8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 4b8d76cb..1cc75de1 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.9
 black==24.4.2
-flake8==7.1.0
+flake8==7.1.1
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From d87a5ad51f92495f37eda321fc6cf43a72ff6218 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 5 Aug 2024 12:16:59 +0000
Subject: [PATCH 148/168] Bump black from 24.4.2 to 24.8.0

Bumps [black](https://github.com/psf/black) from 24.4.2 to 24.8.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.4.2...24.8.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 1cc75de1..459cdbb8 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.9
-black==24.4.2
+black==24.8.0
 flake8==7.1.1
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From 50c488c0125f571f87e30e480e21446338a1b3cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marduk=20Bola=C3=B1os?= <mardukbp@mac.com>
Date: Fri, 9 Aug 2024 18:02:58 +0200
Subject: [PATCH 149/168] Fix #292 -- Change admin widgets' JS media ordering
 (#295)

Select2Mixin now loads admin/js/jquery.init.js, just like the AutocompleteMixin of Django Admin.

---------

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 django_select2/forms.py | 6 +++++-
 tests/test_forms.py     | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 69b1ee3c..85f84672 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -169,8 +169,12 @@ class Select2AdminMixin:
     def media(self):
         css = {**AutocompleteMixin(None, None).media._css}
         css["screen"].append("django_select2/django_select2.css")
+        js = [*Select2Mixin().media._js]
+        js.insert(
+            js.index("django_select2/django_select2.js"), "admin/js/jquery.init.js"
+        )
         return forms.Media(
-            js=Select2Mixin().media._js,
+            js=js,
             css=css,
         )
 
diff --git a/tests/test_forms.py b/tests/test_forms.py
index ddb0f328..71b0b042 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -188,6 +188,7 @@ def test_media(self):
         assert tuple(Select2AdminMixin().media._js) == (
             "admin/js/vendor/select2/select2.full.min.js",
             "admin/js/vendor/select2/i18n/en.js",
+            "admin/js/jquery.init.js",
             "django_select2/django_select2.js",
         )
 

From 458ff01ab9fdf1d6f40df7fa0ae8573cdec2695c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 24 Sep 2024 05:36:06 +0000
Subject: [PATCH 150/168] Bump bandit from 1.7.9 to 1.7.10

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.9 to 1.7.10.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.9...1.7.10)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 459cdbb8..b5693ea6 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.9
+bandit==1.7.10
 black==24.8.0
 flake8==7.1.1
 isort==5.13.2

From 59798d20c65cd09f6682cc18c50d1d7e2ee4df86 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 8 Oct 2024 05:12:15 +0000
Subject: [PATCH 151/168] Bump black from 24.8.0 to 24.10.0

Bumps [black](https://github.com/psf/black) from 24.8.0 to 24.10.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.8.0...24.10.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index b5693ea6..579f7bf6 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.7.10
-black==24.8.0
+black==24.10.0
 flake8==7.1.1
 isort==5.13.2
 pydocstyle[toml]==6.3.0

From de441b64130455a86612419adf774af938ed3589 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 15 Nov 2024 05:25:43 +0000
Subject: [PATCH 152/168] Bump codecov/codecov-action from 4 to 5

Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 4 to 5.
- [Release notes](https://github.com/codecov/codecov-action/releases)
- [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/codecov/codecov-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: codecov/codecov-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 .github/workflows/ci.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0a3c1aa7..af48ff49 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -83,7 +83,7 @@ jobs:
       - run: python -m pip install Django~="${{ matrix.django-version }}.0"
       - run: python -m pip install -e .[test]
       - run: python -m pytest -m "not selenium"
-      - uses: codecov/codecov-action@v4
+      - uses: codecov/codecov-action@v5
 
   Selenium:
     needs:
@@ -109,4 +109,4 @@ jobs:
       - run: python -m pip install Django
       - run: python -m pip install -e .[test,selenium]
       - run: python -m pytest -m selenium
-      - uses: codecov/codecov-action@v4
+      - uses: codecov/codecov-action@v5

From 12e2d60e6dd2d022918991e6e4d55e5930733ccc Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 27 Nov 2024 05:31:05 +0000
Subject: [PATCH 153/168] Bump bandit from 1.7.10 to 1.8.0

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.7.10 to 1.8.0.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.7.10...1.8.0)

---
updated-dependencies:
- dependency-name: bandit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 579f7bf6..2713c027 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.7.10
+bandit==1.8.0
 black==24.10.0
 flake8==7.1.1
 isort==5.13.2

From 352811bc354704f89460ffc5cf2e719df38c49bb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marduk=20Bola=C3=B1os?= <mardukbp@mac.com>
Date: Tue, 10 Dec 2024 17:29:44 +0100
Subject: [PATCH 154/168] Fix #297 -- Add Django admin' inline formset support
 (#300)

As described in #249 and #297 django-select2 does not currently work
with selects added dynamically in the Django admin.

The solution was implemented in #249 and all credit should go to Jurrian
Tromp. I only added a small correction:

```diff
- jqRow.find('.select2-container').remove()
+ jqRow.find('.django-select2').parent().find('.select2-container').remove()
```

to only remove `.select2-container` when it is a sibling of
`.django-select2`. Otherwise the wrong `.select2-container` might get
deleted.

---------

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 django_select2/static/django_select2/django_select2.js | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/django_select2/static/django_select2/django_select2.js b/django_select2/static/django_select2/django_select2.js
index 01db20b5..935033d3 100644
--- a/django_select2/static/django_select2/django_select2.js
+++ b/django_select2/static/django_select2/django_select2.js
@@ -68,7 +68,11 @@
   }
 
   $(function () {
-    $('.django-select2').djangoSelect2()
+    $('.django-select2').not('[name*=__prefix__]').djangoSelect2()
+
+    document.addEventListener('formset:added', (event) => {
+        $(event.target).find('.django-select2').djangoSelect2()
+    })
   })
 
   return $.fn.djangoSelect2

From 94c70dc47695a9292eb468229b072fcf90eccdb0 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Tue, 10 Dec 2024 17:33:48 +0100
Subject: [PATCH 155/168] Upgrade to Baseline2024 compliant JS code (#307)

Run `styleling --fix`.
---
 .../static/django_select2/django_select2.js    | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/django_select2/static/django_select2/django_select2.js b/django_select2/static/django_select2/django_select2.js
index 935033d3..23447d54 100644
--- a/django_select2/static/django_select2/django_select2.js
+++ b/django_select2/static/django_select2/django_select2.js
@@ -10,21 +10,21 @@
   }
 }(function ($) {
   'use strict'
-  var init = function ($element, options) {
+  const init = function ($element, options) {
     $element.select2(options)
   }
 
-  var initHeavy = function ($element, options) {
-    var settings = $.extend({
+  const initHeavy = function ($element, options) {
+    const settings = $.extend({
       ajax: {
         data: function (params) {
-          var result = {
+          const result = {
             term: params.term,
             page: params.page,
             field_id: $element.data('field_id')
           }
 
-          var dependentFields = $element.data('select2-dependent-fields')
+          let dependentFields = $element.data('select2-dependent-fields')
           if (dependentFields) {
             dependentFields = dependentFields.trim().split(/\s+/)
             $.each(dependentFields, function (i, dependentField) {
@@ -49,16 +49,16 @@
   }
 
   $.fn.djangoSelect2 = function (options) {
-    var settings = $.extend({}, options)
+    const settings = $.extend({}, options)
     $.each(this, function (i, element) {
-      var $element = $(element)
+      const $element = $(element)
       if ($element.hasClass('django-select2-heavy')) {
         initHeavy($element, settings)
       } else {
         init($element, settings)
       }
       $element.on('select2:select', function (e) {
-        var name = $(e.currentTarget).attr('name')
+        const name = $(e.currentTarget).attr('name')
         $('[data-select2-dependent-fields~=' + name + ']').each(function () {
           $(this).val('').trigger('change')
         })
@@ -71,7 +71,7 @@
     $('.django-select2').not('[name*=__prefix__]').djangoSelect2()
 
     document.addEventListener('formset:added', (event) => {
-        $(event.target).find('.django-select2').djangoSelect2()
+      $(event.target).find('.django-select2').djangoSelect2()
     })
   })
 

From 5cbd569350136af647e5660ba153c0366e37bfe6 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 13 Jan 2025 09:14:52 +0100
Subject: [PATCH 156/168] Bump bandit from 1.8.0 to 1.8.2 (#310)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.8.0 to 1.8.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/PyCQA/bandit/releases">bandit's
releases</a>.</em></p>
<blockquote>
<h2>1.8.2</h2>
<h2>What's Changed</h2>
<ul>
<li>Revert &quot;Start testing with 3.14 alphas&quot; by <a
href="https://github.com/ericwb"><code>@​ericwb</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1217">PyCQA/bandit#1217</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/PyCQA/bandit/compare/1.8.1...1.8.2">https://github.com/PyCQA/bandit/compare/1.8.1...1.8.2</a></p>
<h2>1.8.1</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump docker/build-push-action from 6.9.0 to 6.10.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1209">PyCQA/bandit#1209</a></li>
<li>Update the bug template with latest bandit version by <a
href="https://github.com/ericwb"><code>@​ericwb</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1208">PyCQA/bandit#1208</a></li>
<li>Add Mercedes-Benz to sponsor list by <a
href="https://github.com/ericwb"><code>@​ericwb</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1210">PyCQA/bandit#1210</a></li>
<li>Bump docker/setup-buildx-action from 3.7.1 to 3.8.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1211">PyCQA/bandit#1211</a></li>
<li>[pre-commit.ci] pre-commit autoupdate by <a
href="https://github.com/pre-commit-ci"><code>@​pre-commit-ci</code></a>
in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1213">PyCQA/bandit#1213</a></li>
<li>Start testing with 3.14 alphas by <a
href="https://github.com/ericwb"><code>@​ericwb</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1189">PyCQA/bandit#1189</a></li>
<li>Remove lxml (B320 &amp; B410) from blacklist by <a
href="https://github.com/djbrown"><code>@​djbrown</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1212">PyCQA/bandit#1212</a></li>
<li>Clarify &quot;getting started&quot; docs by <a
href="https://github.com/Flimm"><code>@​Flimm</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/963">PyCQA/bandit#963</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/djbrown"><code>@​djbrown</code></a> made
their first contribution in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1212">PyCQA/bandit#1212</a></li>
<li><a href="https://github.com/Flimm"><code>@​Flimm</code></a> made
their first contribution in <a
href="https://redirect.github.com/PyCQA/bandit/pull/963">PyCQA/bandit#963</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/PyCQA/bandit/compare/1.8.0...1.8.1">https://github.com/PyCQA/bandit/compare/1.8.0...1.8.1</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PyCQA/bandit/commit/c2c336d1273b06fb667a31d4ecb83de7ea23a6cb"><code>c2c336d</code></a>
Revert &quot;Start testing with 3.14 alphas&quot; (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1217">#1217</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/e58379c5089305c845bae6e816e5faa5680b8097"><code>e58379c</code></a>
Clarify &quot;getting started&quot; docs (<a
href="https://redirect.github.com/PyCQA/bandit/issues/963">#963</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/e4da0b351f89a82b5de8dd791cbdd963476b5a11"><code>e4da0b3</code></a>
Remove lxml (B320 &amp; B410) from blacklist (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1212">#1212</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/13d3406dbba67e22d80f8f8e5b182c5f6e45face"><code>13d3406</code></a>
Start testing with 3.14 alphas (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1189">#1189</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/1abd1d7d65bebad99c6a1731216d46203359fa1e"><code>1abd1d7</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1213">#1213</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/8e3c928985e9c4000d74622520b92c322e7b9024"><code>8e3c928</code></a>
Bump docker/setup-buildx-action from 3.7.1 to 3.8.0 (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1211">#1211</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/929d5976f3949f7507d035b98c9b2db9911ab790"><code>929d597</code></a>
Add Mercedes-Benz to sponsor list (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1210">#1210</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/ead671777dd6cff5f995e92c13814a9eb62db13e"><code>ead6717</code></a>
Update the bug template with latest bandit version (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1208">#1208</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/65ddf8f572f6d6068781b3cb970df2e412406b19"><code>65ddf8f</code></a>
Bump docker/build-push-action from 6.9.0 to 6.10.0 (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1209">#1209</a>)</li>
<li>See full diff in <a
href="https://github.com/PyCQA/bandit/compare/1.8.0...1.8.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=bandit&package-manager=pip&previous-version=1.8.0&new-version=1.8.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 2713c027..36f09015 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.8.0
+bandit==1.8.2
 black==24.10.0
 flake8==7.1.1
 isort==5.13.2

From 7fef9f78e263852cae9ca190c44d9983771425a3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 28 Jan 2025 19:32:23 +0100
Subject: [PATCH 157/168] Bump isort from 5.13.2 to 6.0.0 (#311)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [isort](https://github.com/pycqa/isort) from 5.13.2 to 6.0.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/pycqa/isort/releases">isort's
releases</a>.</em></p>
<blockquote>
<h2>6.0.0</h2>
<h2>Changes</h2>
<h2>:boom: Breaking Changes</h2>
<ul>
<li>Remove support for Python 3.8 (<a
href="https://redirect.github.com/pycqa/isort/issues/2327">#2327</a>) <a
href="https://github.com/DanielNoord"><code>@​DanielNoord</code></a></li>
</ul>
<h2>:rocket: Features</h2>
<ul>
<li>Python 3.13 support (<a
href="https://redirect.github.com/pycqa/isort/issues/2306">#2306</a>) <a
href="https://github.com/mayty"><code>@​mayty</code></a></li>
<li>Updates round 3 (<a
href="https://redirect.github.com/pycqa/isort/issues/2334">#2334</a>) <a
href="https://github.com/matthewhughes934"><code>@​matthewhughes934</code></a></li>
<li>Speed up exists_case_sensitive calls (<a
href="https://redirect.github.com/pycqa/isort/issues/2264">#2264</a>) <a
href="https://github.com/correctmost"><code>@​correctmost</code></a></li>
<li>nit: Fix deprecation message link (<a
href="https://redirect.github.com/pycqa/isort/issues/2220">#2220</a>) <a
href="https://github.com/syou6162"><code>@​syou6162</code></a></li>
<li>Ensure that split_on_trailing_comma works with <code>as</code>
imports (<a
href="https://redirect.github.com/pycqa/isort/issues/2340">#2340</a>) <a
href="https://github.com/DanielNoord"><code>@​DanielNoord</code></a></li>
<li>Black profile: enable magic comma (<a
href="https://redirect.github.com/pycqa/isort/issues/2236">#2236</a>) <a
href="https://github.com/MrMino"><code>@​MrMino</code></a></li>
<li>Fix google style test (<a
href="https://redirect.github.com/pycqa/isort/issues/2336">#2336</a>) <a
href="https://github.com/DanielNoord"><code>@​DanielNoord</code></a></li>
<li>Update line_length and single_line_exclusions in google profile (<a
href="https://redirect.github.com/pycqa/isort/issues/2149">#2149</a>) <a
href="https://github.com/jagapiou"><code>@​jagapiou</code></a></li>
<li>Updates round 2 (<a
href="https://redirect.github.com/pycqa/isort/issues/2329">#2329</a>) <a
href="https://github.com/matthewhughes934"><code>@​matthewhughes934</code></a></li>
<li>Dependency updates round 1 (<a
href="https://redirect.github.com/pycqa/isort/issues/2325">#2325</a>) <a
href="https://github.com/matthewhughes934"><code>@​matthewhughes934</code></a></li>
<li>Run <code>pre-commit autoupdate</code> (<a
href="https://redirect.github.com/pycqa/isort/issues/2321">#2321</a>) <a
href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a></li>
</ul>
<h2>:beetle: Fixes</h2>
<ul>
<li>Allow <code>--diff</code> to be used with <code>--jobs</code> (<a
href="https://redirect.github.com/pycqa/isort/issues/2302">#2302</a>) <a
href="https://github.com/mnakama"><code>@​mnakama</code></a></li>
<li><code>wemake</code> has 80 chars hard limit, not 79 (<a
href="https://redirect.github.com/pycqa/isort/issues/2241">#2241</a>) <a
href="https://github.com/sobolevn"><code>@​sobolevn</code></a></li>
<li>Fix errors on <code>main</code> (<a
href="https://redirect.github.com/pycqa/isort/issues/2320">#2320</a>) <a
href="https://github.com/DanielNoord"><code>@​DanielNoord</code></a></li>
<li>Fixed syntax error (<a
href="https://redirect.github.com/pycqa/isort/issues/2289">#2289</a>) <a
href="https://github.com/Sergio-prog"><code>@​Sergio-prog</code></a></li>
<li>fix: typo (<a
href="https://redirect.github.com/pycqa/isort/issues/2298">#2298</a>) <a
href="https://github.com/Rotzbua"><code>@​Rotzbua</code></a></li>
<li>Fix <code>sort_reexports</code> code mangling (<a
href="https://redirect.github.com/pycqa/isort/issues/2283">#2283</a>) <a
href="https://github.com/Helveg"><code>@​Helveg</code></a></li>
<li>fix: correct group by package tokenization (<a
href="https://redirect.github.com/pycqa/isort/issues/2136">#2136</a>) <a
href="https://github.com/glasnt"><code>@​glasnt</code></a></li>
<li>Fix isort-action usage documentation (<a
href="https://redirect.github.com/pycqa/isort/issues/2297">#2297</a>) <a
href="https://github.com/jamescurtin"><code>@​jamescurtin</code></a></li>
<li>Fix CDN for Ace (<a
href="https://redirect.github.com/pycqa/isort/issues/2127">#2127</a>) <a
href="https://github.com/abitrolly"><code>@​abitrolly</code></a></li>
<li>Fix help text (<a
href="https://redirect.github.com/pycqa/isort/issues/2229">#2229</a>) <a
href="https://github.com/stweil"><code>@​stweil</code></a></li>
<li>docs: fix spelling mistake (<a
href="https://redirect.github.com/pycqa/isort/issues/2249">#2249</a>) <a
href="https://github.com/cachho"><code>@​cachho</code></a></li>
</ul>
<h2>:construction_worker: Continuous Integration</h2>
<ul>
<li>UV replacement of Poetry (<a
href="https://redirect.github.com/pycqa/isort/issues/2349">#2349</a>) <a
href="https://github.com/staticdev"><code>@​staticdev</code></a></li>
<li>Make actions happy (<a
href="https://redirect.github.com/pycqa/isort/issues/2311">#2311</a>) <a
href="https://github.com/matthewhughes934"><code>@​matthewhughes934</code></a></li>
<li>Fix GitHub Actions badges (<a
href="https://redirect.github.com/pycqa/isort/issues/2326">#2326</a>) <a
href="https://github.com/hugovk"><code>@​hugovk</code></a></li>
<li>Eliminate <code>actions/cache@v2</code> usage (<a
href="https://redirect.github.com/pycqa/isort/issues/2322">#2322</a>) <a
href="https://github.com/kurtmckee"><code>@​kurtmckee</code></a></li>
<li>feat: add dependabot for GH action update (<a
href="https://redirect.github.com/pycqa/isort/issues/2300">#2300</a>) <a
href="https://github.com/Rotzbua"><code>@​Rotzbua</code></a></li>
<li>Update stage names for <code>pre-commit</code> (<a
href="https://redirect.github.com/pycqa/isort/issues/2296">#2296</a>) <a
href="https://github.com/matthewhughes934"><code>@​matthewhughes934</code></a></li>
</ul>
<h2>:package: Dependencies</h2>
<ul>
<li>Bump <code>poetry</code> to <code>2.0.1</code> (<a
href="https://redirect.github.com/pycqa/isort/issues/2341">#2341</a>) <a
href="https://github.com/DanielNoord"><code>@​DanielNoord</code></a></li>
<li>Fix misc unsafe dependencies (<a
href="https://redirect.github.com/pycqa/isort/issues/2345">#2345</a>) <a
href="https://github.com/staticdev"><code>@​staticdev</code></a></li>
<li>Bump the github-actions group across 1 directory with 5 updates (<a
href="https://redirect.github.com/pycqa/isort/issues/2324">#2324</a>)
@<a href="https://github.com/apps/dependabot">dependabot[bot]</a></li>
<li>Bump gitpython from 3.1.40 to 3.1.41 (<a
href="https://redirect.github.com/pycqa/isort/issues/2223">#2223</a>)
@<a href="https://github.com/apps/dependabot">dependabot[bot]</a></li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/PyCQA/isort/blob/main/CHANGELOG.md">isort's
changelog</a>.</em></p>
<blockquote>
<h1>Changelog</h1>
<p>NOTE: isort follows the <a href="https://semver.org/">semver</a>
versioning standard.
Find out more about isort's release policy <a
href="https://pycqa.github.io/isort/docs/major_releases/release_policy">here</a>.</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PyCQA/isort/commit/0a0b7a830386ba6a31c2ec8316849ae4d1b8240d"><code>0a0b7a8</code></a>
6.0.0</li>
<li><a
href="https://github.com/PyCQA/isort/commit/2d00730d48c2963a02c436f3353552ce24689a79"><code>2d00730</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/isort/issues/2349">#2349</a>
from PyCQA/revert-2347-revert-2346-ci/uv-replacement...</li>
<li><a
href="https://github.com/PyCQA/isort/commit/16bb0e2d9b7c42edccf4e1ab292d27e9da908e5c"><code>16bb0e2</code></a>
Return user_options</li>
<li><a
href="https://github.com/PyCQA/isort/commit/73abbc8ec7cffc68d9e9c6c47935b46aed5b3665"><code>73abbc8</code></a>
Fix dev and optional dependencies</li>
<li><a
href="https://github.com/PyCQA/isort/commit/8b3828d756d2a359d1b44021c132821ce5955bdf"><code>8b3828d</code></a>
Pin UV version</li>
<li><a
href="https://github.com/PyCQA/isort/commit/02258755eb35111700745a47cce907865c67021a"><code>0225875</code></a>
Remove pip and virtualenv usage</li>
<li><a
href="https://github.com/PyCQA/isort/commit/3d49bc0c44392100bf04b46014fdfc1e9c276f36"><code>3d49bc0</code></a>
Revert &quot;Revert &quot;UV replacement of Poetry&quot;&quot;</li>
<li><a
href="https://github.com/PyCQA/isort/commit/b3760ab1b8844fd4a2c59adee3e0bf3f420fd418"><code>b3760ab</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/isort/issues/2347">#2347</a>
from PyCQA/revert-2346-ci/uv-replacement-for-poetry</li>
<li><a
href="https://github.com/PyCQA/isort/commit/cc12cce681098bba70bd78efe76140bdc39792d6"><code>cc12cce</code></a>
Revert &quot;UV replacement of Poetry&quot;</li>
<li><a
href="https://github.com/PyCQA/isort/commit/f7ab073fda5ddab3651fc4438c4e7e16853b3bca"><code>f7ab073</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/isort/issues/2346">#2346</a>
from PyCQA/ci/uv-replacement-for-poetry</li>
<li>Additional commits viewable in <a
href="https://github.com/pycqa/isort/compare/5.13.2...6.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=isort&package-manager=pip&previous-version=5.13.2&new-version=6.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 36f09015..9ab2d6ed 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.8.2
 black==24.10.0
 flake8==7.1.1
-isort==5.13.2
+isort==6.0.0
 pydocstyle[toml]==6.3.0

From d8f5b3344958f3e04710b87995d378acbc210a47 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 29 Jan 2025 05:08:35 +0000
Subject: [PATCH 158/168] Bump black from 24.10.0 to 25.1.0

Bumps [black](https://github.com/psf/black) from 24.10.0 to 25.1.0.
- [Release notes](https://github.com/psf/black/releases)
- [Changelog](https://github.com/psf/black/blob/main/CHANGES.md)
- [Commits](https://github.com/psf/black/compare/24.10.0...25.1.0)

---
updated-dependencies:
- dependency-name: black
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 9ab2d6ed..5cd20868 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.8.2
-black==24.10.0
+black==25.1.0
 flake8==7.1.1
 isort==6.0.0
 pydocstyle[toml]==6.3.0

From 9e3d9b6e272890f4aeb7ec060b2e2fac56c135e3 Mon Sep 17 00:00:00 2001
From: Mike Manger <ohmanger@gmail.com>
Date: Sun, 9 Feb 2025 14:40:58 +0000
Subject: [PATCH 159/168] Drop official support for EOL Python and Django
 versions (#313)

* Drop Django < 4.2 LTS support
* Drop Django 5.0 support
* Drop Python < 3.10 support
* Update CI node version to lts/*

---------

Co-authored-by: Johannes Maron <johannes@maron.family>
---
 .github/workflows/ci.yml    |  9 ++++-----
 .nvmrc                      |  1 +
 django_select2/forms.py     | 19 +++----------------
 example/example/settings.py |  2 --
 pyproject.toml              | 11 +++++------
 tests/test_forms.py         | 32 +-------------------------------
 tests/test_views.py         |  6 +-----
 tests/testapp/settings.py   |  4 ----
 8 files changed, 15 insertions(+), 69 deletions(-)
 create mode 100644 .nvmrc

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index af48ff49..7438534a 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -44,7 +44,7 @@ jobs:
       - uses: actions/checkout@v4
       - uses: actions/setup-node@v4
         with:
-          node-version: '12.x'
+          node-version-file: '.nvmrc'
       - run: npm install -g standard
       - run: standard
 
@@ -66,14 +66,13 @@ jobs:
     strategy:
       matrix:
         python-version:
-          - "3.8"
-          - "3.9"
           - "3.10"
           - "3.11"
+          - "3.12"
+          - "3.13"
         django-version:
-          - "3.2"
-          - "4.1"
           - "4.2"
+          - "5.1"
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v4
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 00000000..b009dfb9
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+lts/*
diff --git a/django_select2/forms.py b/django_select2/forms.py
index 85f84672..6c5e191e 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -60,8 +60,8 @@
 from itertools import chain
 from pickle import PicklingError  # nosec
 
-import django
 from django import forms
+from django.contrib.admin.utils import lookup_spawns_duplicates
 from django.contrib.admin.widgets import AutocompleteMixin
 from django.core import signing
 from django.db.models import Q
@@ -71,13 +71,6 @@
 from .cache import cache
 from .conf import settings
 
-if django.VERSION < (4, 0):
-    from django.contrib.admin.utils import (
-        lookup_needs_distinct as lookup_spawns_duplicates,
-    )
-else:
-    from django.contrib.admin.utils import lookup_spawns_duplicates
-
 
 class Select2Mixin:
     """
@@ -96,15 +89,9 @@ class Select2Mixin:
     @property
     def i18n_name(self):
         """Name of the i18n file for the current language."""
-        if django.VERSION < (4, 1):
-            from django.contrib.admin.widgets import SELECT2_TRANSLATIONS
-            from django.utils.translation import get_language
-
-            return SELECT2_TRANSLATIONS.get(get_language())
-        else:
-            from django.contrib.admin.widgets import get_select2_language
+        from django.contrib.admin.widgets import get_select2_language
 
-            return get_select2_language()
+        return get_select2_language()
 
     def build_attrs(self, base_attrs, extra_attrs=None):
         """Add select2 data attributes."""
diff --git a/example/example/settings.py b/example/example/settings.py
index 6eef77a3..7fed8450 100644
--- a/example/example/settings.py
+++ b/example/example/settings.py
@@ -105,8 +105,6 @@
 
 USE_I18N = True
 
-USE_L10N = True
-
 USE_TZ = True
 
 
diff --git a/pyproject.toml b/pyproject.toml
index d6ce5548..2f0ff4da 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,19 +20,18 @@ classifiers = [
   "Programming Language :: Python",
   "Programming Language :: Python :: 3",
   "Programming Language :: Python :: 3 :: Only",
-  "Programming Language :: Python :: 3.8",
-  "Programming Language :: Python :: 3.9",
   "Programming Language :: Python :: 3.10",
   "Programming Language :: Python :: 3.11",
+  "Programming Language :: Python :: 3.12",
+  "Programming Language :: Python :: 3.13",
   "Framework :: Django",
-  "Framework :: Django :: 3.2",
-  "Framework :: Django :: 4.1",
   "Framework :: Django :: 4.2",
+  "Framework :: Django :: 5.1",
   "Topic :: Software Development",
 ]
-requires-python = ">=3.8"
+requires-python = ">=3.10"
 dependencies = [
-  "django>=3.2",
+  "django>=4.2",
   "django-appconf>=0.6.0"
 ]
 
diff --git a/tests/test_forms.py b/tests/test_forms.py
index 71b0b042..c42d457f 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -2,7 +2,6 @@
 import os
 from collections.abc import Iterable
 
-import django
 import pytest
 from django.db.models import QuerySet
 from django.urls import reverse
@@ -751,7 +750,7 @@ def test_widgets_selected_after_validation_error(
         assert len(city_names_from_browser) != City.objects.count()
         assert city_names_from_browser == city_names_from_db
 
-        # selecting a city reaaly does it
+        # selecting a city really does it
         city_option = driver.find_element(
             By.CSS_SELECTOR, ".select2-results li:nth-child(2)"
         )
@@ -851,7 +850,6 @@ def widget_fixture(request):
     return widget_class(**widget_kwargs)
 
 
-@pytest.mark.skipif(django.VERSION < (4, 1), reason="Only for Django 4.1+")
 @pytest.mark.parametrize(
     "locale,expected",
     [
@@ -868,7 +866,6 @@ def test_i18n_name_property_with_country_code_in_locale(widget, locale, expected
         assert widget.i18n_name == expected
 
 
-@pytest.mark.skipif(django.VERSION < (4, 1), reason="Only for Django 4.1+")
 def test_i18n_media_js_with_country_code_in_locale(widget):
     translation.activate("fr-FR")
     assert tuple(widget.media._js) == (
@@ -876,30 +873,3 @@ def test_i18n_media_js_with_country_code_in_locale(widget):
         "admin/js/vendor/select2/i18n/fr.js",
         "django_select2/django_select2.js",
     )
-
-
-@pytest.mark.skipif(django.VERSION >= (4, 1), reason="Only for Django 4.0 and previous")
-@pytest.mark.parametrize(
-    "locale,expected",
-    [
-        ("fr-FR", None),
-        # Some locales with a country code are natively supported by select2's i18n
-        ("pt-BR", "pt-BR"),
-        ("sr-Cyrl", "sr-Cyrl"),
-    ],
-)
-def test_i18n_name_property_with_country_code_in_locale_for_older_django(
-    widget, locale, expected
-):
-    """No fallback for locale with an unsupported country code."""
-    with translation.override(locale):
-        assert widget.i18n_name == expected
-
-
-@pytest.mark.skipif(django.VERSION >= (4, 1), reason="Only for Django 4.0 and previous")
-def test_i18n_media_js_with_country_code_in_locale_for_older_django(widget):
-    translation.activate("fr-FR")
-    assert tuple(widget.media._js) == (
-        "admin/js/vendor/select2/select2.full.min.js",
-        "django_select2/django_select2.js",
-    )
diff --git a/tests/test_views.py b/tests/test_views.py
index 745dbfad..b1bf8a46 100644
--- a/tests/test_views.py
+++ b/tests/test_views.py
@@ -1,5 +1,6 @@
 import json
 
+from django.urls import reverse
 from django.utils.encoding import smart_str
 
 from django_select2.cache import cache
@@ -11,11 +12,6 @@
 )
 from tests.testapp.models import Genre
 
-try:
-    from django.urls import reverse
-except ImportError:
-    from django.core.urlresolvers import reverse
-
 
 class TestAutoResponseView:
     def test_get(self, client, artists):
diff --git a/tests/testapp/settings.py b/tests/testapp/settings.py
index f6673aa9..09d58dfb 100644
--- a/tests/testapp/settings.py
+++ b/tests/testapp/settings.py
@@ -1,7 +1,5 @@
 import os.path
 
-import django
-
 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
 DEBUG = True
 
@@ -40,7 +38,5 @@
 
 SECRET_KEY = "123456"
 
-if django.VERSION < (4, 0):
-    USE_L10N = True
 USE_I18N = True
 USE_TZ = True

From 1353d8e2c8d9d53dab5745c2b0015cc7200dad4c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Feb 2025 10:51:42 +0100
Subject: [PATCH 160/168] Bump flake8 from 7.1.1 to 7.1.2 (#314)

Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.1 to 7.1.2.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PyCQA/flake8/commit/fffee8ba9dc5903484f99390e6c7f4bbef59bda7"><code>fffee8b</code></a>
Release 7.1.2</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/19001f77f3a8edccfd2d4c71e3c0fd7ed7fcb329"><code>19001f7</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/flake8/issues/1966">#1966</a>
from PyCQA/limit-procs-to-file-count</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/f35737a32d8283fd0d3456bd9919718ff2d1b077"><code>f35737a</code></a>
avoid starting unnecessary processes when file count is limited</li>
<li>See full diff in <a
href="https://github.com/pycqa/flake8/compare/7.1.1...7.1.2">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flake8&package-manager=pip&previous-version=7.1.1&new-version=7.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 5cd20868..bf5a98ee 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.8.2
 black==25.1.0
-flake8==7.1.1
+flake8==7.1.2
 isort==6.0.0
 pydocstyle[toml]==6.3.0

From 10061a352b177bf61febd62c49ca69af5ce59e4e Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 17 Feb 2025 10:52:06 +0100
Subject: [PATCH 161/168] Bump bandit from 1.8.2 to 1.8.3 (#315)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.8.2 to 1.8.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/PyCQA/bandit/releases">bandit's
releases</a>.</em></p>
<blockquote>
<h2>1.8.3</h2>
<h2>What's Changed</h2>
<ul>
<li>Bump docker/build-push-action from 6.10.0 to 6.11.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1220">PyCQA/bandit#1220</a></li>
<li>Bump docker/build-push-action from 6.11.0 to 6.12.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1221">PyCQA/bandit#1221</a></li>
<li>Bump docker/build-push-action from 6.12.0 to 6.13.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1222">PyCQA/bandit#1222</a></li>
<li>[pre-commit.ci] pre-commit autoupdate by <a
href="https://github.com/pre-commit-ci"><code>@​pre-commit-ci</code></a>
in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1229">PyCQA/bandit#1229</a></li>
<li>Update bug template to include latest released versions by <a
href="https://github.com/ericwb"><code>@​ericwb</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1218">PyCQA/bandit#1218</a></li>
<li>Add markupsafe.Markup XSS plugin by <a
href="https://github.com/Daverball"><code>@​Daverball</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1225">PyCQA/bandit#1225</a></li>
<li>Warn not error on an nonexistant test given by <a
href="https://github.com/ericwb"><code>@​ericwb</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1230">PyCQA/bandit#1230</a></li>
<li>Bump sigstore/cosign-installer from 3.7.0 to 3.8.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1233">PyCQA/bandit#1233</a></li>
<li>Bump docker/setup-buildx-action from 3.8.0 to 3.9.0 by <a
href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1234">PyCQA/bandit#1234</a></li>
<li>B107: Skip None values in hardcoded password detection by <a
href="https://github.com/lukehinds"><code>@​lukehinds</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1232">PyCQA/bandit#1232</a></li>
<li>Pytorch fix by <a
href="https://github.com/lukehinds"><code>@​lukehinds</code></a> in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1231">PyCQA/bandit#1231</a></li>
</ul>
<h2>New Contributors</h2>
<ul>
<li><a href="https://github.com/Daverball"><code>@​Daverball</code></a>
made their first contribution in <a
href="https://redirect.github.com/PyCQA/bandit/pull/1225">PyCQA/bandit#1225</a></li>
</ul>
<p><strong>Full Changelog</strong>: <a
href="https://github.com/PyCQA/bandit/compare/1.8.2...1.8.3">https://github.com/PyCQA/bandit/compare/1.8.2...1.8.3</a></p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PyCQA/bandit/commit/8ff25e07e487f143571cc305e56dd0253c60bc7b"><code>8ff25e0</code></a>
Pytorch fix (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1231">#1231</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/def123ac6dc581a4240a0656319251a46ab80d45"><code>def123a</code></a>
B107: Skip None values in hardcoded password detection (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1232">#1232</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/00b1e9545a5574a440b82a75c48ebeb4c2915e40"><code>00b1e95</code></a>
Bump docker/setup-buildx-action from 3.8.0 to 3.9.0 (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1234">#1234</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/a324f420e60b72cae9994fdd3725f285be1007b2"><code>a324f42</code></a>
Bump sigstore/cosign-installer from 3.7.0 to 3.8.0 (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1233">#1233</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/affd4fd1f506819de211797f3ea4e11114c31bf1"><code>affd4fd</code></a>
Warn not error on an nonexistant test given (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1230">#1230</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/5e3e694325563a0a07053efd162a661f418948bb"><code>5e3e694</code></a>
Add markupsafe.Markup XSS plugin (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1225">#1225</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/6133e08d26f3c24e279872d0a85d221f078518a9"><code>6133e08</code></a>
Update bug template to include latest released versions (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1218">#1218</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/7619cc4d787923ed836014e28f8970f2955ff7c0"><code>7619cc4</code></a>
[pre-commit.ci] pre-commit autoupdate (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1229">#1229</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/33487819d4e11ef4d949882dce4a6508f2d46715"><code>3348781</code></a>
Bump docker/build-push-action from 6.12.0 to 6.13.0 (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1222">#1222</a>)</li>
<li><a
href="https://github.com/PyCQA/bandit/commit/ef0090fd2a56dd420d7578a631e5e24bca952a49"><code>ef0090f</code></a>
Bump docker/build-push-action from 6.11.0 to 6.12.0 (<a
href="https://redirect.github.com/PyCQA/bandit/issues/1221">#1221</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/PyCQA/bandit/compare/1.8.2...1.8.3">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=bandit&package-manager=pip&previous-version=1.8.2&new-version=1.8.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index bf5a98ee..10f3b354 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.8.2
+bandit==1.8.3
 black==25.1.0
 flake8==7.1.2
 isort==6.0.0

From 6e6fdd9cdd3c83305306d7c6eb0626392929c461 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 27 Feb 2025 05:59:34 +0000
Subject: [PATCH 162/168] Bump isort from 6.0.0 to 6.0.1

Bumps [isort](https://github.com/PyCQA/isort) from 6.0.0 to 6.0.1.
- [Release notes](https://github.com/PyCQA/isort/releases)
- [Changelog](https://github.com/PyCQA/isort/blob/main/CHANGELOG.md)
- [Commits](https://github.com/PyCQA/isort/compare/6.0.0...6.0.1)

---
updated-dependencies:
- dependency-name: isort
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 10f3b354..f9f720f9 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.8.3
 black==25.1.0
 flake8==7.1.2
-isort==6.0.0
+isort==6.0.1
 pydocstyle[toml]==6.3.0

From f78152762510ceca949ca8302ac83db9795ed0d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marduk=20Bola=C3=B1os?= <mardukbp@mac.com>
Date: Sat, 15 Mar 2025 17:50:37 +0100
Subject: [PATCH 163/168] Fix  #136  -- Support dependent fields in formsets
 (#316)

* Find the closest common ancestor of two chained selects instead of
assuming it is a form.
* Try to find the dependent field by its name attribute using a two-fold
search strategy: exact match otherwise ends with

Special thanks to @rez0n
---
 django_select2/static/django_select2/django_select2.js | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/django_select2/static/django_select2/django_select2.js b/django_select2/static/django_select2/django_select2.js
index 23447d54..f299e367 100644
--- a/django_select2/static/django_select2/django_select2.js
+++ b/django_select2/static/django_select2/django_select2.js
@@ -26,9 +26,16 @@
 
           let dependentFields = $element.data('select2-dependent-fields')
           if (dependentFields) {
+            const findElement = function (selector) {
+              const result = $(selector, $element.closest(`:has(${selector})`))
+              if (result.length > 0) return result
+              else return null
+            }
             dependentFields = dependentFields.trim().split(/\s+/)
             $.each(dependentFields, function (i, dependentField) {
-              result[dependentField] = $('[name=' + dependentField + ']', $element.closest('form')).val()
+              const nameIs = `[name=${dependentField}]`
+              const nameEndsWith = `[name$=-${dependentField}]`
+              result[dependentField] = (findElement(nameIs) || findElement(nameEndsWith)).val()
             })
           }
 

From e92e0902caa5976a6132b6d2fc5efbc2eeb0b48c Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 3 Apr 2025 08:52:04 +0200
Subject: [PATCH 164/168] Bump flake8 from 7.1.2 to 7.2.0 (#322)

Bumps [flake8](https://github.com/pycqa/flake8) from 7.1.2 to 7.2.0.
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/PyCQA/flake8/commit/16f5f28a384f0781bebb37a08aa45e65b9526c50"><code>16f5f28</code></a>
Release 7.2.0</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/ebad305769bbf62d92901a1b9c9121c1b4fec00b"><code>ebad305</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/flake8/issues/1974">#1974</a>
from PyCQA/update-plugins</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/d56d569ce40a623a17c212ea7f2b306714f27f31"><code>d56d569</code></a>
update versions of pycodestyle / pyflakes</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/a7e8f6250c23e71546ca4cc35322bc06fe90f9f4"><code>a7e8f62</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/flake8/issues/1973">#1973</a>
from PyCQA/py39-plus</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/9d55ccdb729d1255b9cf09438b6073b05b9ce52c"><code>9d55ccd</code></a>
py39+</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/e492aeb385f87c0520c65d32747763209ed1da21"><code>e492aeb</code></a>
Merge pull request <a
href="https://redirect.github.com/pycqa/flake8/issues/1967">#1967</a>
from PyCQA/unnecessary-mocks</li>
<li><a
href="https://github.com/PyCQA/flake8/commit/fa2ed7145cdf80fd983c2a436226a074f9a9d664"><code>fa2ed71</code></a>
remove a few unnecessary mocks in test_checker_manager</li>
<li>See full diff in <a
href="https://github.com/pycqa/flake8/compare/7.1.2...7.2.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=flake8&package-manager=pip&previous-version=7.1.2&new-version=7.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index f9f720f9..f879331e 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.8.3
 black==25.1.0
-flake8==7.1.2
+flake8==7.2.0
 isort==6.0.1
 pydocstyle[toml]==6.3.0

From e5f41e6edba004d35f94915ff5e2559f44853412 Mon Sep 17 00:00:00 2001
From: Johannes Maron <johannes@maron.family>
Date: Mon, 26 May 2025 14:52:29 +0200
Subject: [PATCH 165/168] Merge commit from fork

---
 django_select2/forms.py |  4 ++--
 tests/test_forms.py     | 11 +++++++++++
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/django_select2/forms.py b/django_select2/forms.py
index 6c5e191e..f94a8c1e 100644
--- a/django_select2/forms.py
+++ b/django_select2/forms.py
@@ -255,8 +255,6 @@ def __init__(self, attrs=None, choices=(), **kwargs):
         """
         super().__init__(attrs, choices)
 
-        self.uuid = str(uuid.uuid4())
-        self.field_id = signing.dumps(self.uuid)
         self.data_view = kwargs.pop("data_view", self.data_view)
         self.data_url = kwargs.pop("data_url", self.data_url)
 
@@ -275,6 +273,8 @@ def get_url(self):
 
     def build_attrs(self, base_attrs, extra_attrs=None):
         """Set select2's AJAX attributes."""
+        self.uuid = str(uuid.uuid4())
+        self.field_id = signing.dumps(self.uuid)
         default_attrs = {
             "data-ajax--url": self.get_url(),
             "data-ajax--cache": "true",
diff --git a/tests/test_forms.py b/tests/test_forms.py
index c42d457f..a2b87522 100644
--- a/tests/test_forms.py
+++ b/tests/test_forms.py
@@ -359,6 +359,17 @@ def test_theme_setting(self, settings):
         widget = self.widget_cls(data_view="heavy_data_1")
         assert 'data-theme="classic"' in widget.render("name", None)
 
+    def test_cache_key_leak(self):
+        bob = self.widget_cls(data_url="/test/")
+        alice = self.widget_cls(data_url="/test/")
+        bob.render("name", "value")
+        bob_key_request_1 = bob._get_cache_key()
+        alice.render("name", "value")
+        assert bob._get_cache_key() != alice._get_cache_key()
+        bob.render("name", "value")
+        bob_key_request_2 = bob._get_cache_key()
+        assert bob_key_request_1 != bob_key_request_2
+
 
 class TestModelSelect2Mixin(TestHeavySelect2Mixin):
     form = forms.AlbumModelSelect2WidgetForm(initial={"primary_genre": 1})

From ae98b9a99e931b7f3c2c86e0195f2e91c35053c1 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 17 Jun 2025 05:35:54 +0000
Subject: [PATCH 166/168] Bump bandit from 1.8.3 to 1.8.5

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.8.3 to 1.8.5.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.8.3...1.8.5)

---
updated-dependencies:
- dependency-name: bandit
  dependency-version: 1.8.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index f879331e..b864cf2d 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.8.3
+bandit==1.8.5
 black==25.1.0
 flake8==7.2.0
 isort==6.0.1

From 6c9863097c80a80a78af87f8f5797c81dd73395a Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 23 Jun 2025 05:42:37 +0000
Subject: [PATCH 167/168] Bump flake8 from 7.2.0 to 7.3.0

Bumps [flake8](https://github.com/pycqa/flake8) from 7.2.0 to 7.3.0.
- [Commits](https://github.com/pycqa/flake8/compare/7.2.0...7.3.0)

---
updated-dependencies:
- dependency-name: flake8
  dependency-version: 7.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index b864cf2d..3cf8e528 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,5 +1,5 @@
 bandit==1.8.5
 black==25.1.0
-flake8==7.2.0
+flake8==7.3.0
 isort==6.0.1
 pydocstyle[toml]==6.3.0

From e5aa01f3b9d2251423b392f61f85d93f821dad58 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 7 Jul 2025 06:15:34 +0000
Subject: [PATCH 168/168] Bump bandit from 1.8.5 to 1.8.6

Bumps [bandit](https://github.com/PyCQA/bandit) from 1.8.5 to 1.8.6.
- [Release notes](https://github.com/PyCQA/bandit/releases)
- [Commits](https://github.com/PyCQA/bandit/compare/1.8.5...1.8.6)

---
updated-dependencies:
- dependency-name: bandit
  dependency-version: 1.8.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
---
 linter-requirements.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/linter-requirements.txt b/linter-requirements.txt
index 3cf8e528..b50417c9 100644
--- a/linter-requirements.txt
+++ b/linter-requirements.txt
@@ -1,4 +1,4 @@
-bandit==1.8.5
+bandit==1.8.6
 black==25.1.0
 flake8==7.3.0
 isort==6.0.1
