Search code examples
pythondjangopython-2.7django-filter

How to create link for django filter


Scenario:

Products can have multiple attributes defined in the database, I want to be able to filter by those attributes.

Since i have not found a way to use dynamic attributes using django-filter, this is currently achieved by using django filter MethodFilter which parses the attributes passed as query string as:

/products?attribute=size_2&attribute=color_red

url like this is parsed and it works.

The problem is building the url:

I couldn't find a reasonable way to build the url, that would take current search parameters into account and add/replace those parameters.

Django seems to be forcing me to use urlconf but django-filter uses query string parameters.

What i try to achieve is this:

The user is on page /products?attribute=size_10 which display all products with that size. When he clicks th link "color red" the new url becomes: /products?attribute=size_10&attribute=color_red

Can you point me to the django way of implementing this?


Solution

  • if you include "django.core.context_processors.request", in your middleware then the request.get is accessible in your templates.

    you could then build a filter that will return what 'GET' variables you want when building the link you are talking about.

    here is code for one that i did:

    @register.simple_tag(takes_context=True)
    def lessonapp_preserved_filters(context, url, dayofweek):
        opts = context.get('opts')
        preserved_filters = context.get('preserved_filters')
    
        parsed_url = list(urlparse(url))
        parsed_qs = dict(parse_qsl(parsed_url[4]))
        merged_qs = dict()
    
        if opts and preserved_filters:
            preserved_filters = dict(parse_qsl(preserved_filters))
    
            match_url = '/%s' % url.partition(get_script_prefix())[2]
            try:
                match = resolve(match_url)
            except Resolver404:
                pass
            else:
                current_url = '%s:%s' % (match.app_name, match.url_name)
                changelist_url = 'admin:%s_%s_changelist' % (opts.app_label, opts.model_name)
                if changelist_url == current_url and '_changelist_filters' in preserved_filters:
                    preserved_filters = dict(parse_qsl(preserved_filters['_changelist_filters']))
    
            preserved_filters['dayofweek__exact'] = dayofweek
    
            merged_qs.update(preserved_filters)
    
    
        merged_qs.update(parsed_qs)
    
        parsed_url[4] = urlencode(merged_qs)
        return urlunparse(parsed_url)
    

    and then in the template i use it like this:

    {% lessonapp_preserved_filters adm_url '1' %}