Django 之 模板层

模板层

Django 模板是一些文本字符串,作用是把文档的表现与数据区分开。模板定义一些占位符和基本的逻辑(模板标签),规定如何显示文档。通常,模板用于生成HTML,不过 Django 模板可以生成任何基于文本的格式。

利用Django 模板后端朝前端页面传递数据的方式有两种:

第一种:以字典的形式传递数据
name = 'linwow'
return render(request,'index.html',{'name':name})

第二种:只能用在键和值的变量名相同的情况下,且会导入所以变量,即使不需要用到的也会被导入
name = 'linwow'
password = '123'
return render(request,'index.html',locals()) 

模板系统能优雅处理很多复杂的数据结构,例如列表、字典和自定义的对象。遍历 Django 模板中复杂数据结构的关键是点号(.)。点号可以访问字典的键、属性、方法或对象的索引。

view.py:
import datetime
def index(request):
    string = "hello linwow!"  # 字符串
    mylist = [111, 222, 333]  # 列表
    mydict = {"name": "linwow", "password": 123}  # 字典
    mydate = datetime.date(1999, 12, 30)  # 日期对象
    def func():
        return '你调用了我?'
    class Person(object):
        def __init__(self, name):
            self.name = name
        def func(self):
            return self.name
        @classmethod
        def index(cls):
            return 'cls'
        @staticmethod
        def bar(name, age):
            return 'bar'
    obj = Person("linwow")  # 自定义类对象
    return render(request, "index.html",locals())
    
index.html:
<p>我是传过来的字符串>>>{{string}}</p>
<p>我是传过来的列表>>>{{ mylist }}</p>
<p>我是传过来的列表中的索引2>>>{{ mylist.2 }}</p>
<p>我是传过来的字典>>>{{ mydict.name }}</p>
<p>我是传过来的日期>>>{{ mydate.year }}</p>
<p>我是传过来的函数>>>{{ func }}</p> # 后端传函数名到前端,会自动加括号调用,但是不支持传参
<p>我是传过来的类对象>>>{{ obj.name }}</p> # 后端传对象到前端,就相当于打印了这个对象
<p>我是传过来的类对象的类方法>>>{{ obj.index }}</p>
<p>我是传过来的类对象的静态方法>>>{{ obj.bar }}</p>

注释:不会展示到前端页面

{#调用python自带的内置方法,可以调用不需要传参的一些内置方法#}

过滤器

模板过滤器是在显示变量之前调整变量值的简单方式。过滤器使用管道符号指定,如下所
示:

{{ name|lower}}

上述代码先通过lower过滤器调整{{ name }}变量的值——把文本转换成小写,然后再显示。过滤器可以串接,即把一个过滤器的输出传给下一个过滤器。

下述示例获取列表中的第一个元素,然后将其转换成大写:

{{ my_list|first|upper}}

有些过滤器可以接受参数。过滤器的参数放在冒号之后,始终放在双引号内。例如:

{{ bio|truncatewords:"30"}}

上述示例显示bio变量的前 30 个词。

下面是几个最重要的过滤器:

  • addslashes:在反斜线、单引号和双引号前面添加一个反斜线。可用于转义字符串。例如:{{ val-ue|addslashes }}。
  • date:根据参数中的格式字符串格式化date或datetime对象(不要加百分号)。例如:{{ ctime|date:‘Y-m-d’}}。
  • length:返回值的长度。对列表来说,返回元素的数量。对字符串来说,返回字符的数量。如果变量未定义,返回0。
  • add把参数加到值上。例如:{{ value|add:“2”}}如果value为4,输出6。
  • default如果value是假值,使用指定的默认值;否则,使用value的值。例如:{{ value|default:“nothing”}}
  • dictsort按参数指定的键排序字典构成的列表,返回排序后的列表。例如:{{ value|dictsort:“name”}}
  • filesizeformat把值格式化为人类可读的文件大小(如’13 KB’、‘4.1 MB’、‘102 bytes’,等等)。例如:{{ value|filesizeformat}}如果value为123456789,输出117.7 MB。
  • first返回列表中的第一个元素。
  • last返回列表中的最后一个元素。
  • length_is如果值的长度与参数相等,返回True,否则返回False。例如:{{ value|length_is:“4”}}
  • safe标记字符串在输出之前无需进一步转义 HTML。关闭自动转义时这个过滤器没有效果。
  • slice返回列表的切片。句法与 Python 的列表切片一样。
  • truncatechars字符串的字符串超过指定长度时截断。截断后的字符串以可翻译的省略号(…)结尾。例如:{{ value|truncatechars:9}}
  • truncatewords在指定的单词个数后截断字符串,按照空格截取文本内容。

强调:

前后端取消转义
前端:
	|safe
后端:
	from django.utils.safestring import mark_safe
	xxx = mark_safe('<h1>我是h1标签</h1>')

标签

if/else

{% if %}计算变量的值,如果为真(即存在、不为空,不是假值),模板系统显示{% if %}和{% endif %}之间的内容。例如:

{% if today_is_weekend%}
<p>Welcome to the weekend!</p>
{% endif%}

{% else %}标签是可选的:

{% if today_is_weekend%}
<p>Welcome to the weekend!</p>
{% else%}
<p>Get back to work.</p>
{% endif%}

if标签还可以有一个或多个{% elif %}子句:

{% if athlete_list%}
Number of athletes:{{ athlete_list|length}}
{% elif athlete_in_locker_room_list%}
<p>Athletes should be out of the locker room soon!</p>
{% elif...
...
{% else%}
<p>No athletes.</p>
{% endif%}

{% if %}支持使用and、or或not测试多个变量,或者取反指定的变量。在同一个标签中可以同时使用and和or,此时,and的优先级比or高。如果需要通过括号指明优先级,应该使用嵌套的if标签。不支持使用括号控制操作的顺序。如果觉得有必要使用括号,可以考虑在模板外部执行逻辑,然后通过专用的模板变量传入结果。或者,直接使用嵌套的{%if %}标签。

for

{% for %}标签用于迭代序列中的各个元素。每次迭代时,模板系统会渲染{% for %}和{% endfor %}之间的内容。{% for %}标签可以嵌套。

<ul>
{% for athlete in athlete_list%}
<li>{{athlete.name}}</li>
{% endfor%}
</ul>

在标签中添加reversed,反向迭代列表:

{% for athlete in athlete_list reversed %}
...
{% endfor %}

{{% empty %}}:当你的for循环对象为空的时候会自动走{{% empty %}}代码块儿的内容

book_list=[]

{% for foo in book_list %}
    {{ foo.name }}
    {% empty %}
        <p>你给我的容器类型是个空啊,无法for循环</p>
{% endfor %}

在循环结束之前,无法“跳出”。如果需要这么做,修改要迭代的变量,只包含需要迭代的值。同样,也没有“continue”语句,不能立即返回到循环的开头。在{% for %}循环内部,可以访问一个名为forloop的模板变量。这个变量有几个属性,通过它们可以获知循环进程的一些信息:

  • forloop.counter的值是一个整数,表示循环的次数。这个属性的值从 1 开始,因此第一次循环时,forloop.counter等于1。
  • forloop.revcounter的值是一个整数,表示循环中剩余的元素数量。第一次循环时,for-loop.revcounter的值是序列中要遍历的元素总数。最后一次循环时,forloop.revcounter的值为1。
  • forloop.revcounter0与forloop.revcounter类似,不过索引是基于零的。第一次循环时,for-loop.revcounter0的值是序列中元素数量减去一。最后一次循环时,forloop.revcounter0的值为0。
  • forloop.first是个布尔值,第一次循环时为True。
  • forloop.last是个布尔值,最后一次循环时为True。

forloop变量只在循环内部可用。模板解析器遇到{% endfor %}时,forloop随之消失。

Django 提供了{% ifequal %}标签。{% ifequal %}标签比较两个值,如果相等,显示{% ifequal %}和{% endifequal %}之间的内容。

创建模板库

不管是自定义标签还是过滤器,第一件事都是创建模板库。创建模板库时必须做的三件事:

  • 在应用名下新建一个名为templatetags文件夹(必须叫这个名字)。
  • 在templatetags目录中创建两个空文件:__ init __.py(告诉 Python 这是包含 Python 代码的包)和存放自定义标签(过滤器)的文件,后者的名称是加载标签所用的名称。
  • 一个有效的标签库必须有一个名为register的模块层变量,其值是template.Library的实例。标签和过滤器都通过这种方式注册。因此,在模块顶部要插入下述代码:
from django import template
register = template.Library()	

例如,自定义的标签(过滤器)保存在 my_tag.py 文件中,那么在模板中要这么加载:

{% load my_tag%}

{% load %}语句加载的是指定的 Python 模块,而不是应用。

自定义过滤器

my_tag.py:
@register.filter(name='myadd')
def index(a,b):
	return a+b
	
index.html:
{% load my_tag %}
{{ 666|myadd:8 }}

自定义标签

my_tag.py:
@register.simple_tag
def plus(a,b,c):
	return a+b+c

index.html
{% load my_tag %}
{% plus 1 2 3 %}

自定义inclusion_tag

my_tag.py:
@register.inclusion_tag('login.html',name='login')
    def login(n):
    	l = [ '第%s项'%i for i in range(n)]
    	return {'l':l}
    	
login.html:
<ul>
	{% for foo in l %}
	<li>{{ foo }}</li>
	{% endfor %}
</ul>

index.html
{% load my_tag %}
{% login 5 %}

模板的继承与导入

模板继承

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。

首先需要在被继承的模板中划分多个区域

{% block 给区域起的名字 %}
	...
{% endblock %}

通常情况下一个模板中应该至少有三块

{% block css %}
	页面css代码块
{% endblock %}

{% block js %}
	页面js代码块
{% endblock %}

{% block content %}
	页面主体内容
{% endblock %}

子板继承模板

先继承模板所有的内容
{% extends 'home.html' %}
然后根据block块的名字修改指定区域的内容
{% block content %}
	<h1>登录页面</h1>
	<form action="">
	<p>username:<input type="text" class="form-control"></p>
	<p>password:<input type="text" class="form-control"></p>
	<input type="submit" class="btn btn-success">
	</form>
{% endblock %}

extends 标签是这里的关键,它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时,首先它将定位父模版。

模板的导入:

将一段html当做模块的方式导入到另一个html展示

{% include '想导入的html文件名' %}

静态文件配置

{% load static %}  

<link rel='stylesheet' href="{% static 'css/mycss.css'%}">  # 第一种方式
<link rel='stylesheet' href="{% get_static_prefix %}css/mycss.css">  # 第二种方式

Django 模板查找机制: Django 查找模板的过程是在每个 app 的 templates 文件夹中找(而不只是当前 app 中的代码只在当前的 app 的 templates 文件夹中找)。各个 app 的 templates 形成一个文件夹列表,Django 遍历这个列表,一个个文件夹进行查找,当在某一个文件夹找到的时候就停止,所有的都遍历完了还找不到指定的模板的时候就是 Template Not Found (过程类似于Python找包)。这样设计有利当然也有弊,有利是的地方是一个app可以用另一个app的模板文件,弊是有可能会找错了。所以我们使用的时候在 templates 中建立一个 app 同名的文件夹,这样就好了。

这就需要把每个app中的 templates 文件夹中再建一个 app 的名称,仅和该app相关的模板放在 app/templates/app/ 目录下面,

猜你喜欢

转载自blog.csdn.net/linwow/article/details/91463078
今日推荐