Skip to content

Instantly share code, notes, and snippets.

@leibowitz
Last active October 7, 2022 18:19
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save leibowitz/7a237ea8151f2d238b19ec0da5db545c to your computer and use it in GitHub Desktop.
Save leibowitz/7a237ea8151f2d238b19ec0da5db545c to your computer and use it in GitHub Desktop.
Django Autocomplete with limit_choices_to support
from django.contrib.admin.options import BaseModelAdmin
from django.contrib.admin.views.autocomplete import AutocompleteJsonView
from django.contrib.admin.widgets import (
AutocompleteSelect, AutocompleteSelectMultiple,
)
from django.utils.http import urlencode
from urllib.parse import unquote, quote_plus, parse_qsl
class AutocompleteUrl(object):
def get_url_params(self):
return {
'limit_choices_to': quote_plus(urlencode(self.rel.limit_choices_to))
}
def get_url(self):
url = super().get_url()
return url + '?' + urlencode(self.get_url_params())
class ManyToManyAutocompleteSelect(AutocompleteUrl, AutocompleteSelectMultiple):
pass
class ForeignKeyAutocompleteSelect(AutocompleteUrl, AutocompleteSelect):
pass
class LimitAutocompleteJsonView(AutocompleteJsonView):
# Filter the results with the arguments passed to the url
def get_queryset(self):
qs = super().get_queryset()
limit_choices_to = self.request.GET.get('limit_choices_to')
if not limit_choices_to:
return qs
params = dict(parse_qsl(unquote(limit_choices_to)))
return qs.complex_filter(params)
class HelperAdmin(BaseModelAdmin):
limit_choices_fields = []
def autocomplete_view(self, request):
return LimitAutocompleteJsonView.as_view(model_admin=self)(request)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name in self.limit_choices_fields:
db = kwargs.get('using')
kwargs['widget'] = ForeignKeyAutocompleteSelect(
db_field.remote_field,
self.admin_site,
using=db)
return super().formfield_for_foreignkey(db_field, request, **kwargs)
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name in self.limit_choices_fields:
db = kwargs.get('using')
kwargs['widget'] = ManyToManyAutocompleteSelect(
db_field.remote_field,
self.admin_site,
using=db)
return super().formfield_for_manytomany(db_field, request, **kwargs)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment