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
    }

