Filter View in Django
How to make advanced filter view in djangoIn this tutorial we will make a filter view with a form for filtering data from columns, and (so it won't be a simple POST) we will use generic view with pagination. You may check screen shots at the end of the article.
As an example I'll use my Baldurs Gate Characters Catalogue - it has may fields which can be used for filtering: We start with a extended generic view: The main part of our template looks like this: And the URL is /bgate/filter/
How to create a filterWe will start with designing a form which will contain fields we want to use. I've chosen "race", "class", "gender" and "level" fields. First tree are string, and the last one is integer. My form looks like this Most important is the onsubmit form attribute:
document.FORM_NAME.FIELD_NAME.valueWe could use QueryString and GET but we would get not so nice URLs, and we wouldn't have data validation as with normal URLs, so this trick makes use of standard URLs to get all those goodies. The rest of the form are select fields. I could place all options in the form, but I didn't want it to get ugly. As for "level" I've choosen my own "values". Note: by "0" in all fields I mean "any valune" - no filter rule for this field. The view sends all the data: When I send the form I can get URL like /bgate/filter/Elf/Mage/Female/0/. It's time for URL mapping rules: One int and tree string fields. Now our form variables will be passed to a view which looks like this: I've added expected variables to the view with default value: , race='0', klass='0', gender='0', level='0' ("0" means no filter rule). Next I "select" all the characters (the SQL query isn't performed yet): characters = Character.objects.all().order_by('-id'), and then I can filter this QuerySet as I want using nifty ORM feature - I can add rules not in one command but in many (so it easy to add them in this case). Note that "level" filed doesn't return ints but strings. __range is between A and B, __gte - greater or equal than A.
Our view is working but it needs the last polish - form needs to remember it's values, and we have to make those pagination URLs. So we need to pass filter variables from the view to the template: Now we can use a trick like this: So our form looks like this: And pagination urls: