django-autocomplete-light tutorial ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Overview ======== Autocompletes are based on 3 moving parts: - widget, does the initial rendering, - javascript widget initialization code, to trigger the autocomplete, - and a view used by the widget script to get results from. .. _queryset-view: Create an autocomplete view =========================== The only purpose of the autocomplete view is to serve relevant suggestions for the widget to propose to the user. DAL leverages Django's `class based views `_ and `Mixins `_ to for code reuse. .. note:: Do **not** miss the `Classy Class-Based Views `_ website which helps a lot to work with class-based views in general. In this tutorial, we'll learn to make autocompletes backed by a :django:term:`QuerySet`. Suppose we have a Country :django:term:`Model` which we want to provide a `Select2 `_ autocomplete widget for in a form. If a users types an "f" it would propose "Fiji", "Finland" and "France", to authenticated users only. The base view for this is :py:class:`~dal_select2.views.Select2QuerySetView`. .. code-block:: python from dal import autocomplete from your_countries_app.models import Country class CountryAutocomplete(autocomplete.Select2QuerySetView): def get_queryset(self): # Don't forget to filter out results depending on the visitor ! if not self.request.user.is_authenticated(): return Country.objects.none() qs = Country.objects.all() if self.q: qs = qs.filter(name__istartswith=self.q) return qs .. note:: For more complex filtering, refer to official documentation for the :django:label:`queryset-api`. .. _register-view: Register the autocomplete view ============================== Create a :django:label:`named url` for the view, ie: .. code-block:: python from your_countries_app.views import CountryAutocomplete urlpatterns = [ url( 'country-autocomplete/$', CountryAutocomplete.as_view(), name='country-autocomplete', ), ] .. danger:: As you might have noticed, we have just exposed data through a public URL. Please don't forget to do proper permission checks in get_queryset. Use the view in a Form widget ============================= We can now use the autocomplete view our Person form, for its ``birth_country`` field that's a ``ForeignKey``. So, we're going to :django:label:`override the default ModelForm fields`, to use a widget to select a Model with Select2, in our case by passing the name of the url we have just registered to :py:class:`~dal_select2.widgets.ModelSelect2`: .. code-block:: python from dal import autocomplete from django import forms class PersonForm(forms.ModelForm): class Meta: model = Person fields = ('__all__') widgets = { 'birth_country': autocomplete.ModelSelect2(url='country-autocomplete') } If we need the country autocomplete view for a widget used for a ManyToMany relation instead of a ForeignKey, with a model like that: .. code-block:: python class Person(models.Model): visited_countries = models.ManyToMany('your_countries_app.country') Then we would use the :py:class:`~dal_select2.widgets.ModelSelect2Multiple` widget, ie.: .. code-block:: python widgets = { 'visited_countries': autocomplete.ModelSelect2Multiple(url='country-autocomplete') } Using autocompletes in the admin ================================ We can make ModelAdmin to :django:label:`use our form`, ie: .. code-block:: python from django.contrib import admin from your_person_app.models import Person from your_person_app.forms import PersonForm class PersonAdmin(admin.ModelAdmin): form = PersonForm admin.site.register(Person, PersonAdmin) Note that this also works with inlines, ie: .. code-block:: python class PersonInline(admin.TabularInline): model = Person form = PersonForm