header

Django-Select2

version coverage license

Custom autocomplete fields for Django.

Documentation

Documentation available at https://django-select2.readthedocs.io/.

Note

Django’s admin comes with builtin support for Select2 via the autocomplete_fields feature.

Installation

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:

INSTALLED_APPS = [
    # other django apps…
    'django.contrib.admin',
    # other 3rd party apps…
    'django_select2',
]

Add django_select to your URL root configuration:

from django.urls import include, path

urlpatterns = [
    # other patterns…
    path("select2/", include("django_select2.urls")),
    # other patterns…
]

The 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 DummyCache backend will not work!

The default cache backend is 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

# macOS
brew install redis

# install Redis python client
python3 -m pip install django-redis

Next, add the cache configuration to your settings.py as follows:

CACHES = {
    # … default cache config and others
    "select2": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}

# 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

  • jQuery is not included in the package since it is expected that in most scenarios this would already be available.

Quick Start

Here is a quick example to get you started:

First make sure you followed the installation instructions above. Once everything is setup, let’s start with a simple example.

We have the following model:

# models.py
from django.conf import settings
from django.db import models


class Book(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    co_authors = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='co_authored_by')

Next, we create a model form with custom Select2 widgets.

# forms.py
from django import forms
from django_select2 import forms as s2forms

from . import models


class AuthorWidget(s2forms.ModelSelect2Widget):
    search_fields = [
        "username__icontains",
        "email__icontains",
    ]


class CoAuthorsWidget(s2forms.ModelSelect2MultipleWidget):
    search_fields = [
        "username__icontains",
        "email__icontains",
    ]


class BookForm(forms.ModelForm):
    class Meta:
        model = models.Book
        fields = "__all__"
        widgets = {
            "author": AuthorWidget,
            "co_authors": CoAuthorsWidget,
        }

A simple class based view will do, to render your form:

# views.py
from django.views import generic

from . import forms, models


class BookCreateView(generic.CreateView):
    model = models.Book
    form_class = forms.BookForm
    success_url = "/"

Make sure to add the view to your urls.py:

# urls.py
from django.urls import include, path

from . import views

urlpatterns = [
    # … other patterns
    path("select2/", include("django_select2.urls")),
    # … other patterns
    path("book/create", views.BookCreateView.as_view(), name="book-create"),
]

Finally, we need a little template, myapp/templates/myapp/book_form.html

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Create Book</title>
    {{ form.media.css }}
    <style>
        input, select {width: 100%}
    </style>
</head>
<body>
    <h1>Create a new Book</h1>
    <form method="POST">
        {% csrf_token %}
        {{ form.as_p }}
        <input type="submit">
    </form>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    {{ form.media.js }}
</body>
</html>

Done - enjoy the wonders of Select2!

Changelog

See Github releases.

All Contents

Contents:

Indices and tables