在模板内切片 paginator.page_range
Slicing paginator.page_range inside a template
我在从 ListView
视图返回的模板中有 page_obj
。现在,我想在当前页面之前和之后创建指向多个页面的链接。因此,我想这样分割 page_obj.paginator.page_range
:page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]
。这在 django shell 中有效,但出于某种原因,当我将其作为模板时,有一个 Template Syntax Error, Could not parse the remainder: '[page_obj.number-3:page_obj.number+4]' from 'page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]'
。这种情况有解决方法吗?
P.S。我知道我可以使用整个 page_obj.paginator.page_range
然后使用 if 语句来检查页面是否在要求的范围内,但我认为它有点低效。
正如我在评论中所述,Django 模板语言不包含正常的 python 语法。这样做的原因是 Django 旨在分离网站的逻辑和设计。如果需要执行一些复杂的逻辑,您需要使用模板标签或过滤器。
根据您的需要,可以使用包含标记或采用 page_range
和 return 切片版本的简单过滤器。考虑到我们只能将一个参数传递给它,这里的模板过滤器不是很有用,这意味着它不是非常可定制的。假设您的分页看起来非常相似,或者您可能会将使用的模板传递给标签。
首先,您需要在您的应用程序中创建一个 templatetags
子包,然后在其中添加包含您的标签的文件(例如 pagination_tags.py
)。布局类似于:
your_app/
__init__.py
models.py
templatetags/
__init__.py
pagination_tags.py
views.py
现在您要在文件中 pagination_tags.py
编写标签。作为参考,您可以阅读文档中 Custom template tags and filters 上的 howto。
首先我们声明register
,它是template.Library
的一个实例。之后我们将编写我们的模板标签/过滤器。我们将使用 inclusion_tag
:
from django import template
register = template.Library()
@register.inclusion_tag('pagination_tag.html')
def show_pagination(page_obj, **kwargs):
left = kwargs.get('left', 3)
right = kwargs.get('right', 4)
pages_iter = page_obj.paginator.page_range[page_obj.number - left:page_obj.number + right]
template = kwargs.get('template', 'default_pagination_template.html')
return {**kwargs, 'page_obj': page_obj, 'pages_iter': pages_iter, 'template': template}
现在我们将有一个名为 pagination_tag.html
的简单模板,它将简单地扩展作为关键字参数或 default_pagination_template.html
:
传递的模板名称
{% extends template %}
现在在 default_pagination_template.html
或任何其他模板中,我们可以使用字典中的所有变量,我们的函数 show_pagination
returns:
{% for page_num in pages_iter %}
Display page links here, etc.
{% endfor %}
您可以根据需要修改此实现。我也将 default_pagination_template.html
的设计和实现留给你。
现在在您要使用它的模板中,首先我们将加载这些标签。然后我们将使用它们:
{% load pagination_tags %}
...
{% show_pagination page_obj left=5 right=6 template="some_custom_template.html" %}
我在从 ListView
视图返回的模板中有 page_obj
。现在,我想在当前页面之前和之后创建指向多个页面的链接。因此,我想这样分割 page_obj.paginator.page_range
:page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]
。这在 django shell 中有效,但出于某种原因,当我将其作为模板时,有一个 Template Syntax Error, Could not parse the remainder: '[page_obj.number-3:page_obj.number+4]' from 'page_obj.paginator.page_range[page_obj.number-3:page_obj.number+4]'
。这种情况有解决方法吗?
P.S。我知道我可以使用整个 page_obj.paginator.page_range
然后使用 if 语句来检查页面是否在要求的范围内,但我认为它有点低效。
正如我在评论中所述,Django 模板语言不包含正常的 python 语法。这样做的原因是 Django 旨在分离网站的逻辑和设计。如果需要执行一些复杂的逻辑,您需要使用模板标签或过滤器。
根据您的需要,可以使用包含标记或采用 page_range
和 return 切片版本的简单过滤器。考虑到我们只能将一个参数传递给它,这里的模板过滤器不是很有用,这意味着它不是非常可定制的。假设您的分页看起来非常相似,或者您可能会将使用的模板传递给标签。
首先,您需要在您的应用程序中创建一个 templatetags
子包,然后在其中添加包含您的标签的文件(例如 pagination_tags.py
)。布局类似于:
your_app/
__init__.py
models.py
templatetags/
__init__.py
pagination_tags.py
views.py
现在您要在文件中 pagination_tags.py
编写标签。作为参考,您可以阅读文档中 Custom template tags and filters 上的 howto。
首先我们声明register
,它是template.Library
的一个实例。之后我们将编写我们的模板标签/过滤器。我们将使用 inclusion_tag
:
from django import template
register = template.Library()
@register.inclusion_tag('pagination_tag.html')
def show_pagination(page_obj, **kwargs):
left = kwargs.get('left', 3)
right = kwargs.get('right', 4)
pages_iter = page_obj.paginator.page_range[page_obj.number - left:page_obj.number + right]
template = kwargs.get('template', 'default_pagination_template.html')
return {**kwargs, 'page_obj': page_obj, 'pages_iter': pages_iter, 'template': template}
现在我们将有一个名为 pagination_tag.html
的简单模板,它将简单地扩展作为关键字参数或 default_pagination_template.html
:
{% extends template %}
现在在 default_pagination_template.html
或任何其他模板中,我们可以使用字典中的所有变量,我们的函数 show_pagination
returns:
{% for page_num in pages_iter %}
Display page links here, etc.
{% endfor %}
您可以根据需要修改此实现。我也将 default_pagination_template.html
的设计和实现留给你。
现在在您要使用它的模板中,首先我们将加载这些标签。然后我们将使用它们:
{% load pagination_tags %}
...
{% show_pagination page_obj left=5 right=6 template="some_custom_template.html" %}