Registry / web-framework / django-select2

django-select2

JSON →
library8.4.8pypypiunverified

django-select2 provides a robust Django integration for the popular Select2 JavaScript library, enhancing dropdowns with search, remote data loading, and custom rendering. The current version is 8.4.8, and it sees frequent minor updates and security patches, typically on a monthly or bi-monthly cadence.

pip install django-select2
INSTALL
IMPORT
SIG · DJANGO-SELECT2
D
django-select2
web-frameworkpythonv8.4.8
Install
3.5s avg
Import
—
Disk
66MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.9–3.13
musl
3.9–3.13
Install & Compatibility
Where this runs
tested against v8.4.8 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.000s · 66.5MB
glibc
py 3.10–3.920 runs
installs and imports cleanly · install 3.5s · import 0.000s · 67MB
66MB installed
● package 66MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

Select2Widget
✓ from django_select2.widgets import Select2Widget
✗ from django_select2.forms import Select2Widget

This quickstart demonstrates how to integrate `django-select2` with a simple Django form. Key steps include adding `django_select2` to `INSTALLED_APPS`, including its URL patterns, defining a form with a `Select2Widget`, and ensuring `{{ form.media }}` is present in your template to load the necessary JavaScript and CSS assets.

import os from django import forms from django.conf import settings from django.urls import path, include from django.http import HttpResponse from django.shortcuts import render from django_select2.forms import Select2Widget # Minimal Django settings for testing settings.configure( INSTALLED_APPS=[ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_select2', # Add a placeholder app for templates 'my_app' ], TEMPLATES=[ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(os.path.dirname(__file__), 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ], SECRET_KEY='a_very_secret_key_for_testing_only', DEBUG=True, STATIC_URL='/static/', STATICFILES_FINDERS=[ 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', ], ROOT_URLCONF=__name__, ) # Create a dummy templates directory and file for the quickstart if not os.path.exists('templates'): os.makedirs('templates') with open('templates/quickstart_form.html', 'w') as f: f.write(''' <!DOCTYPE html> <html> <head> <title>Select2 Quickstart</title> {{ form.media.css }} </head> <body> <h1>Select2 Form</h1> <form method="post"> {% csrf_token %} {{ form.as_p }} <button type="submit">Submit</button> </form> {{ form.media.js }} </body> </html> ''') # forms.py (conceptually) class MyChoiceForm(forms.Form): fruit = forms.ChoiceField( choices=[ ('apple', 'Apple'), ('banana', 'Banana'), ('orange', 'Orange'), ('grape', 'Grape'), ('strawberry', 'Strawberry'), ], widget=Select2Widget(attrs={'data-placeholder': 'Select a fruit'}) ) # views.py (conceptually) def quickstart_view(request): if request.method == 'POST': form = MyChoiceForm(request.POST) if form.is_valid(): return HttpResponse(f"You selected: {form.cleaned_data['fruit']}") else: form = MyChoiceForm() return render(request, 'quickstart_form.html', {'form': form}) # urls.py (conceptually) urlpatterns = [ path('select2/', include('django_select2.urls')), path('', quickstart_view, name='quickstart'), ] # To run this, you'd typically have a manage.py and runserver, # but for a self-contained example: # from django.core.management import call_command # call_command('runserver', '0.0.0.0:8000') print("To run this example:") print("1. Ensure you have django and django-select2 installed.") print("2. This code snippet directly configures Django for a basic test.") print("3. In a real project, you'd set up INSTALLED_APPS, URL patterns and templates normally.") print("4. Access '/' to see the form.")
Debug
Known issues
breakingVersion 8.3.0 dropped official support for Django versions older than 4.2 LTS and Python versions older than 3.10. Users on older environments must either upgrade or stick to `django-select2` versions `< 8.3.0`.
fix
Upgrade your Django project to Django 4.2+ and Python to 3.10+ before upgrading `django-select2` to 8.3.0 or later.
affects: < 8.3.0
securityA security vulnerability (CVE-2025-48383 / GHSA-wjrh-hj83-3wh7) was reported where widget instance secret cache keys could leak across multiple requests with a single process.
fix
Upgrade to `django-select2` version 8.4.1 or newer to patch this vulnerability.
affects: All versions < 8.4.1
gotchaFailure to include `django_select2` in `INSTALLED_APPS` and its URL patterns in `urls.py` will prevent assets from loading and AJAX functionality from working.
fix
Ensure `django_select2` is in `settings.INSTALLED_APPS` and `path('select2/', include('django_select2.urls'))` is in your project's `urls.py`.
affects: All
gotchaThe JavaScript and CSS assets for Select2 are loaded via Django's `Media` class. For `django-select2` widgets to function correctly, `{{ form.media }}` must be included in your template, ideally in the `<head>` for CSS and before `</body>` for JavaScript.
fix
Add `{{ form.media }}` (or `{{ form.media.css }}` and `{{ form.media.js }}` separately) to your template where the form is rendered. For best results, place `form.media.css` in the `<head>` and `form.media.js` just before the `</body>` closing tag.
affects: All
gotchaUsing `AutoSelect2Widget` or `HeavySelect2Widget` requires setting up a dedicated view (inheriting from `Select2QuerySetView`) to handle the AJAX requests for data. Without this, the autocomplete functionality will not work.
fix
Create a `Select2QuerySetView` subclass in your `views.py` and map it to a URL pattern that the widget's `data-url` attribute can access.
affects: All
Upgrade
Version history
8.4.8latest on PyPI · released Jan 7, 2026
Audit
Dependencies
DjangorequiredCore framework integration.
Agent activity
9 hits · last 30 days
node
8
Resources
django-select2 — pip install django-select2 · libregistry