我有一个过滤器,其中包含汽车品牌和型号的从属下拉列表。因为我不想在一个页面上显示所有的内容,所以我添加了一个分页器。问题是过滤器工作正常,但它没有在页面
中传递。当过滤器激活时,url看起来像
/cars/?manufacture=2&model=2
如果我转到下一页,我得到的是/cars/?page=2
我想写/cars/?manufacture=2&model=2?page=2
如果我打印{{ posts|length }}
,它确实返回正在过滤的项目的适当数量,因此那里没有问题
我认为问题在于模板中的next和previous按钮,因为它们在下一页之外没有传递任何参数。我如何将过滤器带入分页器。
视图
def allCarsView(request):
model = Post
myFilter = carFilter(request.GET, queryset=Post.objects.all())
posts = myFilter.qs
page = request.GET.get('page', 1)
paginator = Paginator(posts.order_by('date_posted'), 2)
page_obj = paginator.get_page(page)
page_range = paginator.get_elided_page_range(number=page)
context = {
'posts':posts, 'myFilter':myFilter, 'page_range': page_range,
'page': page, 'paginator': paginator, 'page_obj': page_obj
}
return render(request, 'blog/cars.html', context)
Paginator html
<nav aria-label="Page navigation example " class="paginator">
<nav aria-label="Page navigation example " class="paginator">
<ul class="pagination justify-content-center">
<li class="page-item">
{% if page_obj.has_previous %}
<a class="page-link" href="?page={{ page_obj.previous_page_number }}" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
{% else %}
</li>
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %} {% for i in page_obj.paginator.page_range %} {% if page_obj.number == i %}
<li class="page-item active" aria-current="page">
<a class="page-link" href="#">{{ i }}</a>
</li>
{% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %}
<li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
{% endif %} {% endfor %}
<li class="page-item">
{% if page_obj.has_next %}
<a class="page-link" href="?page={{ page_obj.next_page_number }}" aria-label="Previous">
<span aria-hidden="true">»</span>
</a>
{% else %}
</li>
<li class="page-item disabled">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %}
</ul>
</nav>
更新:从做更多的研究,似乎我的问题是与分页器中的url,因为它们不携带任何参数。似乎没有最好的方法来做到这一点,我尝试过的解决方案都一无所获。
更新:试图用这篇文章作为解决方案
视图(在前面的代码中添加)从django中导入模板register = template.Library()
@register.simple_tag
def url_replace(request, field, value):
dict_ = request.GET.copy()
dict_[field] = value
return dict_.urlencode()
模板:
<a class="page-link" href="?{% url_replace request 'page' page_obj.next_page_number %}" aria-label="Previous">
然后得到错误
Invalid block tag on line 88: 'url_replace', expected 'elif', 'else' or 'endif'. Did you forget to register or load this tag?
所以如果我在顶部加上
{% load url_replace %}
抛出错误
'url_replace' is not a registered tag library
尝试从分页器
选择页码{% elif i > page_obj.number|add:'-3' and i < page_obj.number|add:'3' %}
{% if page_obj.number > i %}
<li class="page-item"><a class="page-link" href="?{% querystring_replace request 'page' page_obj.previous_page_number %}">{{ i }}</a></li>
{% endif %}
{% if page_obj.number < i %}
<li class="page-item"><a class="page-link" href="?{% querystring_replace request 'page' page_obj.next_page_number %}">{{ i }}</a></li>
{% endif %}
{% endif %} {% endfor %}
这可以使用自定义模板标记完成,如下面的答案所示。然而,这个答案跳过了创建自定义标记的整个过程,所以让我向您展示如何做到这一点。
Django要求你的自定义标签保存在应用程序的templatetags
文件夹中。所以你的应用程序的文件夹结构应该是这样的:
my-app/
├─ __ini__.py
├─ models.py
├─ views.py
├─ templatetags/
│ ├─ __init__.py
│ ├─ myapp_tags.py
提示:你也可以创建一个专门用于保存自定义标签的新应用程序。这样就可以很容易地在不同的项目中重用它们。确保你的新应用程序在INSTALLED_APPS
列表中。
现在打开myapp_tags.py
文件并创建自定义标记:
# myapp_tags.py
from django import template
register = template.Library()
@register.simple_tag
def querystring_replace(request, key, value):
"""Replace the given `key` with the given `value`
in the request's querystring. The rest of the
querystring remains unchanged.
"""
query_dict = request.GET.copy()
query_dict[key] = value
return query_dict.urlencode()
要在模板中使用这个标记,您需要加载包含标记的文件:<!-- load the file containing the tags -->
{% load myapp_tags %}
<!-- now you can use all the tags from myapp_tags -->
{% querystring_replace request 'page' page_obj.next_page_number %}
每个web请求都是独立的。服务器不记得你之前发送的内容。因此,客户端(浏览器)应该保持(记住)当前上下文并生成适当的请求。
在下面的代码中,您没有传递任何过滤器参数。
<a class="page-link" href="?page={{ page_obj.next_page_number }}"/>
上面的代码实际上呈现如下
<a class="page-link" href="?page=3"/>
要分页AND过滤器,您应该传递过滤器参数。正确的HTML应该如下所示。查询字符串比以前多了。
<a class="page-link" href="?page=3&FILTER_A=FOO&FILTER_B=BAR"/>
有几种方法可以根据前一个请求的查询字符串附加额外的查询字符串。
- 服务器端
- 模板标签
- 第三方
已经有相同的问题了。从两个方面都有很多答案。
如何用其他get变量分页Django ?
https://django-tables2.readthedocs.io/en/latest/
Django-tables是渲染表的一个很好的选项。这个包有自己的分页器模板(HTML)、模板标签和其他代码。如果您选择使用这种方式,下面的代码可能有助于同时使用过滤器和具有内置分页器的表。
class BaseFilteredTableView(SingleTableView):
...
def get_queryset(self, **kwargs):
qs = super().get_queryset(**kwargs)
filter = BarFilter(self.request.GET, queryset=qs, **kwargs)
return filter.qs
客户端
//javascript
<script>
console.log(window.location.href)
</script>
window.location.href
将返回查询字符串。你可以解析它并向每个分页器附加查询字符串a-link