This chapter assumes that you have been through the entire Tutorial.
Any class which implements
guaranteed to work because it provides the methods that are expected by the
view which serves autocomplete contents from ajax, and the methods that are
expected by the form field for validation and by the form widget for rendering.
However, implementing those methods directly would result in duplicate code,
contains all necessary rendering logic but lacks any business-logic, which
means that it is not connected to any data.
If you wanted to make an Autocomplete class that implements business-logic
based on a python list, you would end up with
So far, you should understand that rendering and business logic are not coupled
in autocomplete classes: you can make your own business logic (ie. using
redis, haystack ...) and re-use an existing rendering logic (ie.
For an exhaustive list of Autocomplete classes, refer to the Autocomplete API doc.
One last thing: Autocomplete classes should be registered so that the view can serve them and that form fields and widget be able to re-use them. The registry itself is rather simple and filled with good intentions, refer to Registry API documentation.
Create a basic list-backed autocomplete class¶
Class attributes are thread safe because
always creates a class copy. Hence, registering a custom Autocomplete class for
your model in
your_app/autocomplete_light_registry.py could look like this:
import autocomplete_light class OsAutocomplete(autocomplete_light.AutocompleteListBase): choices = ['Linux', 'BSD', 'Minix'] autocomplete_light.register(OsAutocomplete)
First, we imported
autocomplete_light‘s module. It should contain
everything you need.
Finally, we registered the Autocomplete class. It will be registered with the class name by default.
Another way of achieving the above using the register shortcut could be:
autocomplete_light.register(autocomplete_light.AutocompleteListBase, name='OsAutocomplete', choices=['Linux', 'BSD', 'Minix'])
Using a template to render the autocomplete¶
import autocomplete_light class OsAutocomplete(autocomplete_light.AutocompleteListTemplate): choices = ['Linux', 'BSD', 'Minix'] autocomplete_template = 'your_autocomplete_box.html' autocomplete_light.register(OsAutocomplete)
autocomplete_templatewhich we have customized, if we hadn’t then
AutocompleteTemplate.choice_html()would have fallen back on the parent
choice_templatewhich we haven’t set, so
AutocompleteTemplate.choice_html()will fall back on the parent
See Design documentation for details.
Another way of achieving the above could be:
autocomplete_light.register(autocomplete_light.AutocompleteListTemplate, name='OsAutocomplete', choices=['Linux', 'BSD', 'Minix'], autocomplete_template='your_autocomplete_box.html')
Creating a basic model autocomplete class¶
Registering a custom Autocomplete class for your model in
your_app/autocomplete_light_registry.py can look like this:
from models import Person class PersonAutocomplete(autocomplete_light.AutocompleteModelBase): search_fields = ['^first_name', 'last_name'] autocomplete_light.register(Person, PersonAutocomplete)
An equivalent of this example would be:
autocomplete_light.register(Person, search_fields=['^first_name', 'last_name'])
Overriding the queryset of a model autocomplete to secure an Autocomplete¶
You can override any method of the Autocomplete class. Filtering choices based on the request user could look like this:
class PersonAutocomplete(autocomplete_light.AutocompleteModelBase): search_fields = ['^first_name', 'last_name']) model = Person def choices_for_request(self): if not self.request.user.is_staff: self.choices = self.choices.filter(private=False) return super(PersonAutocomplete, self).choices_for_request() # we have specified PersonAutocomplete.model, so we don't have to repeat # the model class as argument for register() autocomplete_light.register(PersonAutocomplete)
It is very important to note here, that clean() will raise a
ValidationError if a model is selected in a
Use at your own discretion, as this can cause problems when a choice is no longer part of the queryset, just like with django’s Select widget.
Registering the same Autocomplete class for several autocompletes¶
This code registers an autocomplete with name
To register two autocompletes with the same class, pass in a name argument:
autocomplete_light.register(ContactAutocomplete, name='Person', choices=Person.objects.filter(is_company=False)) autocomplete_light.register(ContactAutocomplete, name='Company', choices=Person.objects.filter(is_company=True))