Django Autocomplete Light

3.12.1 · active · verified Tue Apr 14

Django Autocomplete Light (DAL) provides a modern, fresh set of widgets for Django forms and admin, enabling easy integration of autocompletion functionality for fields like foreign keys, many-to-many, and tags. It's currently at version 3.12.1 and typically releases updates in line with Django's development or new feature requirements.

Warnings

Install

Imports

Quickstart

This quickstart demonstrates setting up a basic autocomplete for a `ForeignKey` field in Django using DAL. It involves defining a model, creating an autocomplete view (`CountryAutocomplete`) to serve data, and configuring a form (`CityForm`) to use the `Select2QuerySetView` widget, linking it to the autocomplete URL. Remember to include `dal` and `dal_select2` in `INSTALLED_APPS` before your own application.

import os
import django
from django.conf import settings
from django.db import models
from django import forms
from django.urls import path, reverse_lazy

settings.configure(
    DEBUG=True,
    INSTALLED_APPS=[
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'dal',
        'dal_select2',
        'testapp' # Your app name
    ],
    MIDDLEWARE=[
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ],
    TEMPLATES=[
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            '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',
                ],
            },
        },
    ],
    DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},
    STATIC_URL='/static/',
    SECRET_KEY=os.environ.get('DJANGO_SECRET_KEY', 'a-very-secret-key-for-testing-only'),
    ROOT_URLCONF=__name__,
)

django.setup()

# --- Your app's models.py ---
class Country(models.Model):
    name = models.CharField(max_length=100, unique=True)

    def __str__(self):
        return self.name

    class Meta:
        app_label = 'testapp'


class City(models.Model):
    name = models.CharField(max_length=100)
    country = models.ForeignKey(Country, on_delete=models.CASCADE, related_name='cities')

    def __str__(self):
        return f"{self.name} ({self.country.name})"

    class Meta:
        app_label = 'testapp'


# --- Your app's forms.py ---
import autocomplete_light
from dal_select2.widgets import Select2QuerySetView


class CityForm(forms.ModelForm):
    class Meta:
        model = City
        fields = ('name', 'country')
        widgets = {
            'country': Select2QuerySetView(
                url=reverse_lazy('country-autocomplete'),
                attrs={
                    'data-placeholder': 'Search for a country',
                    'data-minimum-input-length': 2,
                }
            )
        }

# --- Your app's views.py and urls.py combined for quickstart ---
from dal_select2.views import Select2QuerySetView

class CountryAutocomplete(Select2QuerySetView):
    def get_queryset(self):
        # Don't forget to filter out results if a query is provided
        qs = Country.objects.all()
        if self.q:
            qs = qs.filter(name__icontains=self.q)
        return qs

# --- ROOT_URLCONF definitions ---
urlpatterns = [
    path('country-autocomplete/', CountryAutocomplete.as_view(), name='country-autocomplete'),
    # Example: If you were to integrate this form into a view
    # path('city/add/', lambda request: HttpResponse(CityForm().as_p()), name='add-city'),
]

# Example usage (requires setting up Django's test client or a view)
if __name__ == '__main__':
    # This part would typically be in a Django shell or a real view.
    # For demonstration, we'll just show the form rendering.
    from django.core.management import call_command
    from django.db import connection
    with connection.cursor() as cursor:
        cursor.execute("CREATE TABLE testapp_country (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(100) UNIQUE)")
        cursor.execute("CREATE TABLE testapp_city (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(100), country_id INTEGER REFERENCES testapp_country(id) ON DELETE CASCADE)")
        cursor.execute("INSERT INTO testapp_country (name) VALUES ('France')")
        cursor.execute("INSERT INTO testapp_country (name) VALUES ('Germany')")
        cursor.execute("INSERT INTO testapp_country (name) VALUES ('Spain')")
    
    # Print the form HTML to demonstrate the widget integration
    print("\n--- Example City Form HTML ---\n")
    print(CityForm().as_p())
    print("\nCheck Django admin or a custom view for full functionality with the autocomplete URL.")

view raw JSON →