Skip to content

Instantly share code, notes, and snippets.

@georgefs
Created May 11, 2013 20:54
Show Gist options
  • Save georgefs/5561397 to your computer and use it in GitHub Desktop.
Save georgefs/5561397 to your computer and use it in GitHub Desktop.
django advance search form
class FormForAdvancedSearch(forms.Form):
#you can put any field here this is an example so only 1 simple CharField
form_field1 = forms.CharField()
class MyModelAdmin(admin.ModelAdmin):
# the auxiliary search form
advanced_search_form = FormForAdvancedSearch()
# a dictionary of key that will be removed from the GET QueryDict
# this is necessary otherwise ChangeList will complain for malformed
# query string
other_search_fields={}
# standard search
search_fields = ['field1','field2']
def lookup_allowed(self, lookup):
if lookup in self.advanced_search_form.fields.keys():
return True
return super(MyModelAdmin, self).lookup_allowed(lookup)
def queryset(self, request):
qs = super(MyModelAdmin, self).queryset(request)
# probably there is a better way to extract this value this is just
# an example and depends on the type of the form field
form_field1_value = search_fields.get("form_field1",[""])[0]
qs.filter(field3__icontains==form_field1_value)
return qs
def changelist_view(self, request, extra_context=None, **kwargs):
# we need to reset on every request otherwise it will survive and we
# don't want that
self.other_search_fields = {}
extra_context = {'asf':self.advanced_search_form}
# we now need to remove the elements coming from the form
# and save in the other_search_fields dict but it's not allowed
# to do that in place so we need to temporary enable mutability ( I don't think
# it will cause any complicance but maybe someone more exeprienced on how
# QueryDict works could explain it better)
request.GET._mutable=True
for key in asf.fields.keys():
try:
temp = request.GET.pop(key)
except KeyError:
pass # there is no field of the form in the dict so we don't remove it
else:
if temp!=['']: #there is a field but it's empty so it's useless
self.other_search_fields[key] = temp
request.GET_mutable=False
return super(MyModelAdmin, self)\
.changelist_view(request, extra_context=extra_context)
admin.site.register(MyModel, MyModelAdmin)
# you need a templatetag to rewrite the standard search_form tag because the default
# templatetag to render the search form doesn't handle context so here it is:
# remember to put it inside a source file (in my case is custom_search_form.py) that
# lives in project/myapp/templatetags otherwise will not be found by the template engine
from django.contrib.admin.views.main import SEARCH_VAR
from django.template import Library
register = Library()
@register.inclusion_tag('admin/search_form.html', takes_context=True)
def advanced_search_form(context, cl):
"""
Displays a search form for searching the list.
"""
return {
'asf' : context.get('asf'),
'cl': cl,
'show_result_count': cl.result_count != cl.full_result_count,
'search_var': SEARCH_VAR
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment