Lookup Channels

A LookupChannel defines how to search and how to format found objects for display in the interface.

LookupChannels are registered with a “channel name” and fields refer to that name.

You may have only one LookupChannel for a model, or you might define several for the same Model each with different queries, security policies and formatting styles.

Custom templates can be created for channels. This enables adding extra javascript or custom UI. See Customizing Templates


Write your LookupChannel classes in a file name yourapp/lookups.py

(note: inside your app, not your top level project)

Use the @register decorator to register your LookupChannels by name


from ajax_select import register, LookupChannel

class ThingsLookup(LookupChannel):

    model = Things

    def get_query(self, q, request):
          return self.model.objects.filter(title__icontains=q).order_by('title')

If you are using Django >= 1.7 then all lookups.py in all of your apps will be automatically imported on startup.

If Django < 1.7 then you can import each of your lookups in your views or urls. Or you can register them in settings (see below).


class ajax_select.lookup_channel.LookupChannel

Subclass this, setting the model and implementing methods to taste.


model (Model): The Django Model that this lookup channel will search for.
plugin_options (dict): Options passed to jQuery UI plugin that are specific to this channel.
min_length (int): Minimum number of characters user types before a search is initiated.

    This is passed to the jQuery plugin_options.
    It is used in jQuery's UI when filtering results from its own cache.

    It is also used in the django view to prevent expensive database queries.
    Large datasets can choke if they search too often with small queries.
    Better to demand at least 2 or 3 characters.
can_add(user, other_model)

Check if the user has permission to add a ForeignKey or M2M model.

This enables the green popup + on the widget. Default implentation is the standard django permission check.

  • user (User) –
  • other_model (Model) – the ForeignKey or M2M model to check if the User can add.



By default only request.user.is_staff have access.

This ensures that nobody can get your data by simply knowing the lookup URL.

This is called from the ajax_lookup view.

Public facing forms (outside of the Admin) should implement this to allow non-staff to use this LookupChannel.

Parameters:request (Request) –

(HTML) format item for displaying item in the selected deck area.

Parameters:obj (Model) –
Returns:formatted string, may contain HTML.
Return type:str

(HTML) Format item for displaying in the dropdown.

Parameters:obj (Model) –
Returns:formatted string, may contain HTML.
Return type:str

This is used to retrieve the currently selected objects for either ManyToMany or ForeignKey.

Parameters:ids (list) – list of primary keys
Returns:list of Model objects
Return type:list
get_query(q, request)

Return a QuerySet searching for the query string q.

Note that you may return any iterable so you can return a list or even use yield and turn this method into a generator.

  • q (str, unicode) – The query string to search for.
  • request (Request) – This can be used to customize the search by User or to use additional GET variables.

iterable of related_models

Return type:

(QuerySet, list, generator)


The text result of autocompleting the entered query.

For a partial string that the user typed in, each matched result is here converted to the fully completed text.

This is currently displayed only for a moment in the text field after the user has selected the item. Then the item is displayed in the item_display deck and the text field is cleared.

Parameters:obj (Model) –
Returns:The object as string
Return type:str


Versions previous to 1.4 loaded the LookupChannels according to settings.AJAX_LOOKUP_CHANNELS

This will still work. Your LookupChannels will continue to load without having to add them with the new @register decorator.


# settings.py

      # auto-create a channel named 'person' that searches by name on the model Person
      # str: dict
      'person': {'model': 'example.person', 'search_field': 'name'}

      # specify a lookup to be loaded
      # str: tuple
      'song': ('example.lookups', 'SongLookup'),

      # delete a lookup channel registered by an app/lookups.py
      # str: None
      'users': None

One situation where it is still useful: if a resuable app defines a LookupChannel and you want to override that or turn it off. Pass None as in the third example above.

Anything in settings.AJAX_LOOKUP_CHANNELS overwrites anything previously registered by an app.