classFormForAdvancedSearch(forms.Form):#you can put any field here this is an example so only 1 simple CharFieldform_field1=forms.CharField()classMyModelAdmin(admin.ModelAdmin):# the auxiliary search formadvanced_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']deflookup_allowed(self,lookup):iflookupinself.advanced_search_form.fields.keys():returnTruereturnsuper(MyModelAdmin,self).lookup_allowed(lookup)defqueryset(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)returnqsdefchangelist_view(self,request,extra_context=None,**kwargs):# we need to reset on every request otherwise it will survive and we # don't want thatself.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=Trueforkeyinasf.fields.keys():try:temp=request.GET.pop(key)exceptKeyError:pass# there is no field of the form in the dict so we don't remove itelse:iftemp!=['']:#there is a field but it's empty so it's uselessself.other_search_fields[key]=temprequest.GET_mutable=Falsereturnsuper(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 fromdjango.contrib.admin.views.mainimportSEARCH_VARfromdjango.templateimportLibraryregister=Library()@register.inclusion_tag('admin/search_form.html',takes_context=True)defadvanced_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}