Paginate来自django_filter

时间:2017-10-23 12:14:32

标签: python django filter pagination

我对这项技术非常陌生,我想使用django_filter对包含结果的表进行分页(在我的情况下,我想过滤来自Book Model的结果,这些结果显示在HTML表中)。

我尝试了所有文档和论坛帖子,但不知道我做错了什么,或者我是否正确地做了什么。

这是我的代码:

模型

class Book(models.Model):

    name = models.CharField(max_length=350)
    author = models.CharField(max_length=350)
    category = models.CharField(max_length=200)

    def __str__(self):
        return self.name

过滤器

class BookFilter(django_filters.FilterSet):
    name = django_filters.CharFilter(lookup_expr='icontains')
    author = django_filters.CharFilter(lookup_expr='icontains')
    category = django_filters.CharFilter(lookup_expr='icontains')

    class Meta:
        model = Book
        ields = ['name', 'author', 'category',]

视图

class SearchBooksView(ListView):
    template_name = "booksearch.html"
    book_list = Book.objects.all()
    context_object_name = 'book_list'
    paginate_by = 3

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        book_filter = BookFilter(self.request.GET)
        paginator = Paginator(book_filter, self.paginate_by)
        page = self.request.GET.get('page')
            try:
                book_list = paginator.page(page)
            except PageNotAnInteger:
                book_list = paginator.page(1)
            except EmptyPage:
                book_list = paginator.page(paginator.num_pages)

        context['book_list'] = book_list

        return context

** html **

<h1 class="h1"> Search Books </h1>
<form method="get">
    {{ book_filter.form.as_p }}
    <button type="submit">Search</button>
</form>
<div class="container">
    <table>
        <thead>
            <tr>
                <th>Name</th>
                <th>Author</th>
                <th>Category</th>
            </tr>
        </thead>
        <tbody>
        {% for book in book_list %}
            <tr>
                <td>{{ book.name }}</td>
                <td>{{ book.author }}</td>
                <td>{{ book.category }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>
    {% if is_paginated %}
        <ul class="pagination">
        {% if page_obj.has_previous %}
            <li>
                <span><a href="?page={{ page_obj.previous_page_number }}">Previous</a></span>
            </li>
        {% endif %}
            <li class="">
                <span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.</span>
            </li>
        {% if page_obj.has_next %}
            <li>
                <span><a href="?page={{ page_obj.next_page_number }}">Next</a></span>
            </li>
        {% endif %}
        </ul>
        {% else %}
            <p>No books available</p>
        {% endif %}
</div>

使用此代码:

paginator.py, line 84, in count return len(self.object_list)

'BookFilter' has no len()
你能帮帮我吗?谢谢!

2 个答案:

答案 0 :(得分:2)

您需要将已过滤的查询集传递给Paginator,该Paginator可以filterObj.qs进行访问。

来自django_filter docs

  

如果要访问视图中的过滤对象,例如,如果要对它们进行分页,则可以执行此操作。他们在f.qs

所以创建一个像这样的分页响应:

book_filter = BookFilter(self.request.GET)
paginator = Paginator(book_filter.qs, self.paginate_by)

答案 1 :(得分:0)

你正在使用django的通用ListView吗?这个观点已经为你做了分页,你应该重构代码:

class SearchBooksView(ListView):
    model = Book
    template_name = "booksearch.html"
    context_object_name = 'book_list'
    paginate_by = 3

    def get_queryset(self):
        return BookFilter(self.request.GET, queryset=Book.objects.all()).qs