Django templatetag"处理顺序"

Jas*_*eri 10 django django-templates

我正在尝试编写一组模板标记,允许您从模板文件本身轻松指定js和css文件.某些事情{% requires global.css %},以及后来的请求中{% get_required_css %}.

我有这个主要工作,但有几个问题.我们将从"时间"问题开始.

每个模板标签由两个步骤组成,调用/ init和render.每个调用/ init都在调用任何渲染过程之前发生.为了保证所有文件在{% get_required_css %}呈现之前排队,我需要在call/init过程中自己构建所需文件的列表.

因此,我需要按照请求将所有文件收集到一个包中.该context字典显然这个地方,但不幸的是,呼叫/ init不会访问上下文变量.

这有意义吗?有人看到了解决这个问题的方法(不使用hack-y全局request对象)?

将这些存储在本地字典中的另一种可能性,但它们仍然需要以某种方式与请求绑定...可能是某种{% start_requires %}标记?但我也不知道如何做到这一点.

Jac*_* M. 2

我想出了一种更适合您需求的方法。它会给服务器带来更多的负载,但适当的缓存可以帮助减轻大部分负载。下面我概述了一种在每个路径的 CSS 包含相同的情况下应该有效的方法。您需要创建一个视图来包含所有这些文件,但实际上您可以使用此方法优化 CSS,为每个页面仅进行一次 CSS 调用。

import md5
class LoadCss(template.Node):
    def __init__(self, tag_name, css):
        self.css = css
        self.tag_name = tag_name
    def render(self, context):
        request = context['request']
        md5key = md5.new(request.path).hexdigest()
        if md5key not in request.session:
            request.session[md5key] = list()
        ## This assumes that this method is being called in the correct output order.
        request.session[md5key].append(self.css)
        return '<!-- Require %s -->' % self.css
def do_load_css(parser, token):
    tag_name, css = token.split_contents()
    return LoadCss(tag_name, key)
register.tag('requires', do_load_css)

class IncludeCss(template.Node):
    def __init__(self, tag_name):
        self.tag_name = tag_name
    def render(self, context):
        request = context['request']
        md5key = md5.new(request.path).hexdigest()
        return '<link rel="stylesheet" href="/path/to/css/view/%s">' % md5key
def do_include_css(parser, token):
    return IncludeCss(token)
register.tag('get_required_css', do_include_css)
Run Code Online (Sandbox Code Playgroud)

视图.py:

from django.conf import settings
from django.views.decorators.cache import cache_page
import os

@cache_page(60 * 15) ## 15 Minute cache.
def css_view(request, md5key):
    css_requires = request.session.get(md5key, list())
    output = list()
    for css in css_requires:
        fname = os.path.join(settings.MEDIA_ROOT, 'css', css) ## Assumes MEDIA_ROOT/css/ is where the CSS files are.
        f = open(fname, 'r')
        output.append(f.read())
    HttpResponse(''.join(output), mimetype="text/css")
Run Code Online (Sandbox Code Playgroud)

这允许您将 CSS 信息存储在上下文中,然后存储在会话中,并提供视图的输出(使用缓存以使其更快)。当然,这会产生更多的服务器开销。

如果您需要改变的 CSS 不仅仅是路径,那么您可以简单地修改这些md5行来满足您的需求。您可以访问整个请求对象和上下文,因此几乎所有内容都应该在那里。

注意: 在第二次审查时,如果浏览器在填充会话之前获取 CSS,则可能会导致竞争条件。我不相信 Django 是这样工作的,但我现在不想查找它。