I'm trying to filter a ListView based on Users, using a drop down form.
models.py
class Post(models.Model):
...
author = models.ForeignKey('auth.User', verbose_name="Post Author")
views.py
class PostList(ListView):
model = Post
context_object_name = 'posts'
def get_queryset(self):
result = super(PostList, self).get_queryset()
author_filter = self.request.GET.get('author')
if author_filter:
result = Post.objects.filter(Q(author__icontains=author_filter))
return result
post_list.html
<form action="" method="get">
<select name="author" onchange="this.form.submit();">
<option selected="selected" disabled>Select an author</option>
{% all_author as authors %}
{% for author in authors %}
<option value="{{ author }}">{{ author }}</option>
{% endfor %}
</select>
</form>
I am using a custom template tag to render all_authors
and this works fine. When selecting an author, in the urls I can see something is passed (/?author=xxx), but the list is not filtered.
EDIT
Based on andi's suggestion I made it work this way using django filters. But for some reason fields = ['field_name',]
in filters.py is not taken into account, so I'm selecting the fields individually in the template.
views.py
class PostList(FilterView):
model = Post
filter_class = PostFilter
context_object_name = 'posts'
paginate_by = 50
template_name = 'directory/post_list.html'
filters.py
class PostFilter(django_filters.FilterSet):
class Meta:
model = Post
fields = ['author',]
post_list.html
<form action="" method="get">
{{ filter.form.author }}
<input type="submit" />
</form>
EDIT 2
I've found out why the selected fields were not passed correctly, needed to use in views filterset_class =
instead of filter_class =
Ohh, it is really oldschool, error prone and time consuming way of doing the things.
Please give a try to django-filter
library. And create working fine filters with minimum amount of effort! This allows creating very robust filtering strategies while maintaining clean code.
https://django-filter.readthedocs.io/en/latest/guide/usage.html#
below fast draft:
the filter:
import django_filters
class PostFilter(django_filters.FilterSet):
class Meta:
model = Post
fields = ['author']
the view:
from django_filters.views import FilterView
from somwhere.in.your.project.filtersets import PostFilter
class PostList(FilterView):
model = Post
context_object_name = 'posts'
filter_class = PostFilter
in template:
{% extends "base.html" %}
{% block content %}
<form action="" method="get">
{{ filter.form.as_p }}
<input type="submit" />
</form>
{% for obj in filter.qs %}
{{ obj.name }} - ${{ obj.price }}<br />
{% endfor %}
{% endblock %}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With