【问题标题】:Best way to filter ListView with drop down form in Django在 Django 中使用下拉表单过滤 ListView 的最佳方法
【发布时间】:2018-03-11 12:48:36
【问题描述】:

我正在尝试使用下拉表单根据用户过滤 ListView。

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>

我正在使用自定义模板标签来呈现all_authors,这工作正常。选择作者时,在 urls 中我可以看到传递了一些东西 (/?author=xxx),但列表没有被过滤。

编辑

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

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>

编辑 2

我发现为什么选择的字段没有正确传递,需要在视图中使用 filterset_class = 而不是 filter_class =

【问题讨论】:

    标签: django listview filter


    【解决方案1】:

    哦,这真是老派,容易出错且耗时的做事方式。

    请尝试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']
    

    观点:

    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
    

    在模板中:

    {% 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 %}
    

    【讨论】:

    • @robtus88 我提供了 PostList(FilterView) 的示例,只需添加 template_name = 'path/to/your/template.html'
    • 我明白了,现在可以了。我现在唯一的问题是我的模型的所有字段都显示在过滤器中(我只想选择一些),而且我看不到如何设置过滤器的样式(布局)。你知道如何解决这两点吗?
    • 通过过滤器集定义中的 fields = ('field_nam', ) 限制它
    • 视图定义中的小错误:您似乎需要设置filterset_class 而不是filter_class (original code)。除此之外,这非常有帮助。
    • 如果你使用 ListView 的分页器不起作用
    【解决方案2】:

    在您的表单中,尝试更改:

    <option value="{{ author }}">{{ author }}</option>
    

    到这里:

    <option value="{{ author.pk }}">{{ author }}</option>
    

    那么,在你看来:

    if author_filter:
        result = Post.objects.filter(author_id=int(auth_filter))     
    

    【讨论】:

    • 谢谢,但这并没有改变它,当我选择作者时,列表没有更新,我尝试打印 author_filter 但没有任何显示,所以我猜问题出在早期代码
    • url 中的变量已更新,但视图仍然没有任何变化。 author_filter 仍然没有显示任何内容,所以我会说 self.request.GET.get('author') 有问题,或者我的 html 有问题,但我看不到哪一个。如果您知道其他方法可以做到这一点,我会全力以赴:)
    猜你喜欢
    • 1970-01-01
    • 2012-01-14
    • 2020-10-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-05
    • 2020-11-11
    • 2013-11-04
    • 2021-02-05
    相关资源
    最近更新 更多