- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我想弄清楚是否有可能在使用 django-endless-pagination 进行无限滚动的 django 模板中呈现之前对我的查询集进行 View 后处理。
我有特定于 View 的逻辑,它根据上下文从查询集中省略某些结果,并向列表中的对象添加属性以供模板使用。此逻辑不能通过 SQL 执行,因为它不是模型固有的。它必须在 python 中完成。
使用 django-endless-pagination 和其他预滚动的 django 分页模块,所有逻辑似乎都由 templatetags 执行,从而阻止了在渲染阶段之前执行业务逻辑的能力(这是 django 的原则)。
因为我的 View 逻辑在模板标签执行之前遍历结果集,所以我失去了这个模块提供的优化(比如带分页的 SQL 查询,例如 limit 20;offset 20)。每次用户翻页时,我的代码都会遍历整个未分页的结果列表,从而绕过了模板标签提供的惰性分页优势。
除了将我的代码直接移动到分页模块中(我宁愿不这样做并且需要将一堆额外的数据添加到请求上下文中以用于标记中),还有其他选择吗?
谢谢!
最佳答案
如果你看lazy_paginate标签使用 LazyPaginator处理查询集的类。您可以覆盖该类以满足您的目的。为此,您需要编写 Custom Template Tag .更多说明在代码注释中。
*my_app/templatetags/custom_pagination_tags.py*
from django import template
from endless_pagination.templatetags.endless import paginate
from endless_pagination.paginators import LazyPaginator
register = template.Library()
Class CustomLazyPaginator(LazyPaginator):
def page(self, number):
page_obj = super(CustomLazyPaginator, self).page(number)
# page function returns page object from that you could access object_list
object_list = page_obj.object_list
# Do some processing here for your queryset
# Do not remove elements otherwise you will put your self in trouble
# Just add some values in objects as you wanted to
page_obj.object_list = object_list # override here
return page_obj
@register.tag
def custom_lazy_paginate(parser, token):
return paginate(parser, token, paginator_class=CustomLazyPaginator)
现在在模板中加载您的自定义模板标签并改用它:
{% load custom_pagination_tags %}
{% custom_lazy_paginate queryset %}
困难:在 CustomLazyPaginator 类中访问请求上下文的第一种方法
是的,有一种方法可以传递请求上下文,但是为了做到这一点,您需要覆盖 paginate
标记以及 PaginateNode 的
如你所见 here当它调用 render
方法paginator_class
时,它不会传递任何上下文信息。以下是实现该目标的步骤:
在CustomLazyPaginator
中添加__init__
方法:
def __init__(self, *args, **kwargs):
self.context = kwargs.pop('context', None)
super(CustomLazyPaginator, self).__init__(*args, **kwargs)
复制 paginate
标签并将 return
语句从 PaginateNode(paginator_class, objects, **kwargs)
更改为 CustomPaginateNode( paginator_class, objects, **kwargs)
我们将在下面编写 CustomPaginateNode
。
from endless_pagination.templatetags.endless import PAGINATE_EXPRESSION
@register.tag
def paginate(parser, token, paginator_class=None):
# Validate arguments.
try:
tag_name, tag_args = token.contents.split(None, 1)
except ValueError:
msg = '%r tag requires arguments' % token.contents.split()[0]
raise template.TemplateSyntaxError(msg)
# Use a regexp to catch args.
match = PAGINATE_EXPRESSION.match(tag_args)
if match is None:
msg = 'Invalid arguments for %r tag' % tag_name
raise template.TemplateSyntaxError(msg)
# Retrieve objects.
kwargs = match.groupdict()
objects = kwargs.pop('objects')
# The variable name must be present if a nested context variable is passed.
if '.' in objects and kwargs['var_name'] is None:
msg = (
'%(tag)r tag requires a variable name `as` argumnent if the '
'queryset is provided as a nested context variable (%(objects)s). '
'You must either pass a direct queryset (e.g. taking advantage '
'of the `with` template tag) or provide a new variable name to '
'store the resulting queryset (e.g. `%(tag)s %(objects)s as '
'objects`).'
) % {'tag': tag_name, 'objects': objects}
raise template.TemplateSyntaxError(msg)
# Call the node.
return CustomPaginateNode(paginator_class, objects, **kwargs)
删除我们之前调用的以下导入以避免调用原始的 paginate
函数:
from endless_pagination.templatetags.endless import paginate
覆盖 PaginateNode
的 render
方法以将上下文传递给我们的 CustomLazyPaginator
类:
from endless_pagination.templatetags.endless import PaginateNode
from endless_pagination import (
settings,
utils,
)
class CustomPaginateNode(PaginateNode):
def render(self, context):
# Handle page number when it is not specified in querystring.
if self.page_number_variable is None:
default_number = self.page_number
else:
default_number = int(self.page_number_variable.resolve(context))
# Calculate the number of items to show on each page.
if self.per_page_variable is None:
per_page = self.per_page
else:
per_page = int(self.per_page_variable.resolve(context))
# Calculate the number of items to show in the first page.
if self.first_page_variable is None:
first_page = self.first_page or per_page
else:
first_page = int(self.first_page_variable.resolve(context))
# User can override the querystring key to use in the template.
# The default value is defined in the settings file.
if self.querystring_key_variable is None:
querystring_key = self.querystring_key
else:
querystring_key = self.querystring_key_variable.resolve(context)
# Retrieve the override path if used.
if self.override_path_variable is None:
override_path = self.override_path
else:
override_path = self.override_path_variable.resolve(context)
# Retrieve the queryset and create the paginator object.
objects = self.objects.resolve(context)
paginator = self.paginator(
objects, per_page, first_page=first_page, orphans=settings.ORPHANS,
context=context) # <--- passing context here
# Normalize the default page number if a negative one is provided.
if default_number < 0:
default_number = utils.normalize_page_number(
default_number, paginator.page_range)
# The current request is used to get the requested page number.
page_number = utils.get_page_number_from_request(
context['request'], querystring_key, default=default_number)
# Get the page.
try:
page = paginator.page(page_number)
except EmptyPage:
page = paginator.page(1)
# Populate the context with required data.
data = {
'default_number': default_number,
'override_path': override_path,
'page': page,
'querystring_key': querystring_key,
}
context.update({'endless': data, self.var_name: page.object_list})
return ''
简单:在 CustomLazyPaginator 类中访问请求上下文的第二种方法
只需安装 django-contrib-requestprovider并将它添加到 django 的 settings.py 的中间件中,并在任何你想要的地方访问当前请求:
from gadjo.requestprovider.signals import get_request
http_request = get_request()
关于python - 如何在使用 django 无尽分页渲染之前进行结果后处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18704459/
我正在寻找一种使此打印 HTML 代码 fragment 向后兼容旧 Android 版本的简单方法: @TargetApi(Build.VERSION_CODES.KITKAT) private v
我在 GCC 终端 (centos linux) 中为 ATM 项目编译以下 c 和 .h 代码时收到以下错误。请帮忙,因为我是编程新手。 validate_acc.h #ifndef _VALIDA
在写关于 SO 的不同问题的答案时,我制作了这个片段: @import url('https://fonts.googleapis.com/css?family=Shadows+Into+Light'
试图弄清楚我应该如何在 my_div_class 之前放置一个 span 而不是替换所有它。现在它取代了 div,但我不想这样做。我假设它类似于 :before 但不知道如何使用它。 { va
我正在使用选择库 http://github.hubspot.com/select/和 noUiSlider https://refreshless.com/nouislider/ .我面临的问题如下
我是开发新手,独自工作。我正在使用 Xcode 和 git 版本控制。可能我没有适本地组织和做错事,但我通常决定做 promise 只是为了在我破坏一切之前做出安全点。在那一刻,我发现很难恰本地描述我
我想确保在同一个桶和键上读取和写入时,应该更新获取的值,也就是说,应该在对其进行写入操作之后获取它。我怎样才能做到这一点? 我想要的是,如果我更新一个键的值,如果我同时使用不同线程获取值,则更新同一个
我的问题与this有关问题,已经有了答案: yes, there is a happens-before relationship imposed between actionsof the thre
The before and after hook documentation on Relish仅显示 before(:suite) 在 before(:all) 之前调用。 我什么时候应该使用其中
我有 CSV 行,我想在其中检测所有内部双引号,没有文本限定符。这几乎可以正常工作,但我的正则表达式还可以检测双引号后的字符。 CSV 部分: "7580";"Lorem ipsum";"";"Lor
是否可以通过Youtube数据API检查广告是否可以与特定视频一起显示? 我了解contentDetails.licensedContent仅显示视频是否已上传至同一伙伴然后由其声明版权。由于第三者权
考虑一下用漂亮的彩色图表描述的“像素管道” https://developers.google.com/web/fundamentals/performance/rendering/ 我有一个元素(比
之前?
在 MVC3 中,我可以轻松地将 jQuery 脚本标签移动到页面底部“_Layout.vbhtml” 但是,在 ASP.NET MVC3 中,当您使用编辑器模板创建 Controller 时,脚手
悬停时内容被替换,但是当鼠标离开元素时我希望它变回来。我该怎么做? $('.img-wrap').hover(function(){ $(this).find('h4').text('Go
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
已关闭。这个问题是 not reproducible or was caused by typos 。目前不接受答案。 这个问题是由拼写错误或无法再重现的问题引起的。虽然类似的问题可能是 on-top
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 已关闭 9 年前。 有关您编写的代码问题的问题必须在问题本身中描述具体问题 - 并包含有效代码以重现该问题。
版本:qwt 6.0.1我尝试开发频谱的对数缩放。我使用简单的线条来启用缩放plotspectrum->setAxisScaleEngine(QwtPlot::yLeft, new QwtLog10S
我有两个相同的表,I_Subject 和 I_Temp_Subject,我想将 Temp_Subject 表复制到 Subject 表。 I_Temp_Subject 由简单用户使用,I_Subjec
我的印象是第一次绘制发生在触发 DOMContentLoaded 事件之后。特别是,因为我认为为了让第一次绘制发生,需要渲染树,它依赖于 DOM 构造。另外,我知道 DOM 构造完成时会触发 DOMC
我是一名优秀的程序员,十分优秀!