1

I'm making a generic template that will be displaying a list of objects from a queryset:

{% for o in objects %}
    {{ o.name }}
{% endfor %}

I want to be able to use the template in multiple situations, where different sorts of filtering and ordering need to be done. I have created a view function for this:

def display_objects(request, filters, orders, template_name):
    objects = Object.objects.all()
    for filter in filters:
        objects = objects.filter(('%s__%s' % (filter['field'], filter['relationship']), filter['value']))
    for order in orders:
        objects = objects.order_by('-' if 'descending' in order else '' + order['field'])
    # render objects to template with context
    pass

I'm not sure if what I have done so far will even work, but I've run into an issue. I don't know if it's feasible to filter the query set by a parameter captured in the URL with my current function.

For example, if I wanted to display objects pertaining to a certain user I would do something like:

(r'^user/(?P<account_username>[^/]+)/$', display_objects, dict(filters=[{'field':'account__username','relationship':'iexact','value':account_username}], orders=[{'field':'foobar'}], template_name='user.html'))

Obviously, account_username isn't a defined field until the URL is parsed and dispatched to the display_objects function. It would be easy enough to make a view function that takes an account_username parameter, but I want to be able to use the function for displaying other object query sets that will be filtered with different captured parameters.

Is there some way I can pass captured URL parameters to a view function to dynamically filter or order a query set to be displayed?

2 Answers 2

1

Here's one way you can do this:

in urls.py:

(r'^user/(?P<account_username>[^/]+)/$', display_objects, dict(filters=[{'field':'account__username','relationship':'iexact'}], orders=[{'field':'foobar'}], template_name='user.html'))

And then in views.py:

def display_objects(request, filters, orders, template_name, **kwargs):

    objects = Object.objects.all()
    for filter in filters:
        objects = objects.filter(('%s__%s' % (filter['field'], filter['relationship']), kwargs.get(filter['field'])))
    for order in orders:
        objects = objects.order_by('-' if 'descending' in order else '' + order['field'])
    # render objects to template with context
    pass

Although honestly I'm not sure if this is a good way of doing things...

Sign up to request clarification or add additional context in comments.

1 Comment

As I thought about it, I realized that the way that I had structured the view function was probably not optimal. Do you have any suggestions for how else you would dynamically filter and order querysets for templates?
0

You can't pass a string directly to the filter method. You need to translate it into kwargs.

query_string = '%s__%s' % (filter['field'], filter['relationship'])
objects = objects.filter(**{query_string: filter['value']}))

1 Comment

I'm not sure when this happened but his syntax works on 1.4A obj.filter(('key', 'value')). Caught me off guard too but it accepts key/value tuples. !?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.