23.4.7. 玩转Django2.0-模板

1.模板简介

 Django作为web框架,需要一种很便利的方法去动态地生成HTML网页,因此有了模板这个概念。模板包含所需HTML的部分代码以及一些特殊语法

  Django可以配置一个或多个模板引擎(甚至是0,如果不需要使用模板),模板系统有Django模板语言(Django Template Language, DTL)和Jinja2。Django模板语言是Django内置的模板语言,Jinja2是当前Python最流行的模板语言。

变量与标签

  变量是模板中最基本的组成单位,模板变量是由视图函数生成的。如果变量没有被视图函数生成,那么模板引擎解析HTML时,模板变量不会显示在网页上。变量以{{ variable }}表示,variable是变量名,变量的类型可以是Python支持的数据类型,使用如下:

#  variable为字符串类型或整型,如variable = "Python"
{{  variable  }}
#  输出Python

#  variable为字典或数据对象,通过点号(.)来访问其属性值
#  如variable  =  {"name":  "Lily",  "info":  {"home":  "BeiJing",  "homeplace":  "ShangHai"}}
{{  variable.name  }}
#  输出Lily
{{  variable.info.home  }}
#  输出BeiJing

2.模板继承

 模板继承是通过模板标签来实现的,其作用是将多个HTML模板的共同代码集中在一个新的HTML模板中,然用户各个模板可以直接调用新的HTML模板,从而生成HTML网页,这样可以减少模板之间重复的代码。代码如下:

urls.py

path('index01.html', views.index01, name='index01'),

views.py

def index01(request):
    return render(request, 'index01.html')

index01.html

<!DOCTYPE html>
<html lang="en">
<body>
{#    继承base.html模板,调用base.html模板#}
{% extends "base.html" %}
{% block body %}
    <a href="{% url 'index01' %}" target="_blank">首页</a>
    <h1>Hello Django</h1>
    <a href="/logout">logout</a>
{% endblock %}
</body>
</html>

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
</head>
<body>
    {% block body %} {% endblock %}
</body>
</html>

 从index.html看到,模板继承与Python的类继承的原理是一致的,通过继承的方式使其具有父类的功能和属性,然后以重写的方式实现各种开发需求。

3.自定义过滤器

  过滤器主要是对变量的内容进行处理,如替换、反序和转义等。通过过滤器处理变量可以将变量的数据格式和内容转换为我们想要的效果,而且相应减少视图函数的代码量。

在MyDjango项目中添加了user_defined文件夹,在其文件夹下又分别添加了templatetags`文件夹和__init__.py文件。templatetags用于存放自定义过滤器的代码文件,该文件夹也可以存放在项目的APP中,但必须注意的是,文件夹的命名必须为templatetags,否则Django在运行的时候无法识别自定义过滤器。最后在templatetags文件夹下创建myfilter.py文件,该文件是编写自定义过滤器的实现代码。

 完成过滤器的目录搭建,接着是配置过滤器的信息,在配置文件settings.py的INSTALLED_APPS里面添加user_defined。当项目启动时,Django会从INSTALLED_APPS的配置中查找过滤器,若过滤器设置在index的目录下,则只需在INSTALLED_APPS中配置index即可,如下:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'index',
    'user',
    'user_defined',
]

  完成上述两个环境配置后,下一步是编写自定义过滤器的实现代码,在myfilter.py中添加以下代码:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from django import template

# 什么一个模板对象,称为注册过滤器
register = template.Library()


# 声明并定义过滤器
@register.filter
def myreplace(value, args):
    oldValue = str(args).split(':')[0]
    newValue = str(args).split(':')[1]
    return str(value).replace(oldValue, newValue)

上述代码用于实现HTML模板的字符串替换功能,与Python的replace函数相同,过滤器说明如下:

    1、首先导入模板功能template,通过template声明Library对象,将对象赋值给变量register,这一过程称为注册过滤器。

    2、过滤器以函数的形式实现,在函数前使用register.filter装饰器来表示该函数是一个过滤器,函数名可自行命名。

    3、函数参数可设置一个或两个,如上述的参数分别是value和agrs,参数value是HTML模板的变量,参数agrs是过滤器函数定义的函数参数。

    4、过滤器函数最后必须将处理结果返回,否则在使用过程中会出现异常信息。

  最后在HTML模板中使用我们自定义的过滤器,以django_index.html模板的title为例

urls.py

# filter的视图
url(r'^filter.html', views.filter_index, name="filter_index"),

views.py

# 自定义的过滤器views
def filter_index(request):
    type_list = Product.objects.values('type').distinct()
    name_list = Product.objects.values('name', 'type')
    context = {'title': '首页', 'type_list': type_list, 'name_list': name_list}
    return render(request, 'django_index.html', context=context, status=500)
    # return render(request, 'django_index.html', locals(), status=500)

django_index.html

{#加载自己定义的过滤器#}
{% load myfilter %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ title |myreplace:"首页:小健的首页" }}</title>
    <meta charset="utf-8">
</head>
<body>
<ul id="cate_box" class="lf">
    {% for type in type_list %}
        <li>
            <h3><a href="#">{{ type.type }}</a></h3>
            <p>
                {% for name in name_list %}
                    {% if name.type == type.type %}
                        <span>{{ name.name }}</span>

                    {% endif %}
                {% endfor %}
        </li>
    {% endfor %}

</ul>
</body>
</html>