在 django 中使用 jinjia2 代替 DTL

前面我在 django 的设置里注释掉了一些内容,有 django 的后台程序、认证程序、消息框架,后面还会放弃一些,比如 django 的表单,我个人觉得一点都不好用。这不需要设置,不用就行了。还有 django 的模板,我将使用 jinja2 全面代替。这样做有几个理由:

  • jinja2 的速度比 django 自带的 DTL 模板速度要快很多,至少十倍以上。
  • jinja2 模板语法更符合我的习惯,估计对很多人都是的。
  • jinja2 和 DTL 可以共存,如果使用 django 的后台程序,DTL 必须存在。但是,我不是已经放弃了吗?
  • 单独使用 jinja2,虽然会有一些麻烦,但是都可以弥补。

要使用 jinja2 代替 DTL,还得修改 www/settings.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# settings.py

TEMPLATES = [
    {
        # 'BACKEND': 'django.template.backends.django.DjangoTemplates', # 原来的
        'BACKEND': 'django.template.backends.jinja2.Jinja2', # 新添加的
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        # DIRS 必须设置,否则找不到模板,即便 APP_DIRS 设置为 True 也不行,索性把 templates 放在根目录算了
        # 'APP_DIRS': True, # 这一句既然设置了也没用,注释掉算了
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.template.context_processors.static', # 习惯,而且弥补了更换模板后产生的一个问题
                # 'django.contrib.auth.context_processors.auth',
                # 'django.contrib.messages.context_processors.messages',
            ],
            'environment':'www.jinja2.environment', # OPTIONS 添加了这个参数,后面会解释
        },
    },
]
......

# 和模板文件一样,默认的静态文件夹也无效了,必须设置 STATICFILES_DIRS,所以也放在根目录了

STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),
]

现在说说 jinja2 代替 DTL 后出现的问题,主要有三个:

  1. 原来在 DTL 里可以使用 {% static ... %} 的,用来生成静态文件的根。现在不行了。解决方法跟第二个问题一起说。有意思的是,这个问题对我来说不是问题,我以前就不用 {% static %} 的,使用这个之前还要 {% load static %}。前面提到了,我是在 settings.py 里添加一句,之后就可以在模板里用 STATIC_URL 这个变量了,而且和模板是谁无关,跟 request 一样。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # settings.py

    TEMPLATES = [
        {
            ......

            'OPTIONS': {
                'context_processors': [
                    ......

                    'django.template.context_processors.static',
                    ......
                ],
                ......
            },
        },
    ]
  2. {% url ... %} 也不能用了!生成一个 url,比 {% static ... %} 还重要,必须处理!在 settings.py 所在的目录 www 建立一个 jinja2.py 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # jinja2.py

    from django.templatetags.static import static
    from django.urls import reverse
    from jinja2 import Environment


    def environment(**options):
        env = Environment(**options)
        env.globals.update({
            'static': static,
            'url_for': reverse, # 使用了 url_for,让它看起来像是 flask,其实名称随意
        })
        return env

    这个文件会很有用,可以在这里配置 jinja2,过滤器也可以定义在这里面。现在仅有的这些代码配合前面看到的那句添加在 settings.py 里的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # settings.py

    TEMPLATES = [
        {
            ......

            'OPTIONS': {
                ......

                'environment':'www.jinja2.environment',
            },
        },
    ]

    这样在模板里就可以使用 staticurl_for 了,注意用法和从前不一样,如

    1
    <link rel="stylesheet" type="text/css" href="{{static('css/common.css')}}">

    以及

    1
    <a href="{{url_for(views_name,args1=[...],args2=[...],...)}}">...</a>
  3. MIDDLEWARE 里的 django.middleware.csrf.CsrfViewMiddleware 不能用了。csrf 保护,听起来就像是很重要的样子,把这一句注释掉,总觉得失去了什么。处理的办法是原来在模板中使用 {% csrf_token %} 的地方替换为

    1
    <input type="hidden" name="csrfmiddlewaretoken" value="{{csrf_token}}">

至此,settings.py 的配置告一段落。