在Django中使用下拉列表过滤ListView的最佳方法

rob*_*s88 4 django listview filter

我正在尝试使用下拉表单过滤基于用户的ListView.

models.py

class Post(models.Model):
    ...
    author = models.ForeignKey('auth.User', verbose_name="Post Author")
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

我正在使用自定义模板标记进行渲染all_authors,这很好用.选择作者时,在网址中我可以看到传递的内容(/?author = xxx),但列表未被过滤.

编辑

根据andi的建议,我使用django过滤器以这种方式工作.但由于某些原因fields = ['field_name',]filter.py没有考虑在内,所以我在模板中单独选择字段.

views.py

class PostList(FilterView):
    model = Post
    filter_class = PostFilter
    context_object_name = 'posts'
    paginate_by = 50
    template_name = 'directory/post_list.html'
Run Code Online (Sandbox Code Playgroud)

filters.py

class PostFilter(django_filters.FilterSet):

    class Meta:
        model = Post
        fields = ['author',]
Run Code Online (Sandbox Code Playgroud)

post_list.html

<form action="" method="get">
            {{ filter.form.author }}
            <input type="submit" />
        </form>
Run Code Online (Sandbox Code Playgroud)

编辑2

我已经找到了为什么所选字段没有正确传递,需要在视图中使用filterset_class =而不是filter_class =

and*_*abs 6

哦,这真的是老式的,容易出错和耗时的做事方式.

请试试django-filter图书馆.并以最少的努力创建工作精细的过滤器!这允许创建非常强大的过滤策略,同时保持干净的代码

https://django-filter.readthedocs.io/en/latest/guide/usage.html#

以下快速草案:

过滤器:

import django_filters

class PostFilter(django_filters.FilterSet):
    class Meta:
        model = Post
        fields = ['author']
Run Code Online (Sandbox Code Playgroud)

风景:

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
Run Code Online (Sandbox Code Playgroud)

在模板中:

{% 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 %}
Run Code Online (Sandbox Code Playgroud)

  • 视图定义中的小错误:似乎您需要设置 `filterset_class` 而不是 `filter_class` ([原始代码](https://github.com/carltongibson/django-filter/blob/master/django_filters/views. py#L37))。除此之外,这非常有帮助。 (2认同)