模板(template)
一、模板渲染
思考 : 网站如何向客户端返回一个漂亮的页面呢?
-
提示 :
- 漂亮的页面需要
html
、css
、js
. - 可以把这一堆字段串全都写到视图中, 作为
HttpResponse()
的参数,响应给客户端.
- 漂亮的页面需要
-
问题 :
- 视图部分代码臃肿, 耦合度高.
- 这样定义的字符串是不会出任何效果和错误的.
- 效果无法及时查看.有错也不容易及时发现.
-
设想 :
- 是否可以有一个专门定义前端页面的地方, 效果可以及时展示,错误可以及时发现,并且可以降低模块间耦合度!
-
解决问题 :模板
MVT
设计模式中的T
,Template
-
在
Django
中, 将前端的内容定义在模板中, 然后再把模板交给视图调用, 各种漂亮、炫酷的效果就出现
之前演示时使用 HttpResponse来进行测试字符串的返回
也介绍了HttpResponse有三种模式,那么如果我们要对界面渲染的将view中定义的元素展示到html界面的话 该怎么办呢?
1、1: render方法
render
(请求、template_name、上下文=无、content_type=无、状态=无、使用=无)¶
将给定模板与给定上下文字典组合在一起,并返回具有该呈现文本的 HttpResponse
对象。
Django 没有提供返回 TemplateResponse
的快捷方式函数,因为 TemplateResponse
的构造函数提供了与 render()
相同级别的便利性。
必需参数(指定你的 要渲染的html文件)
request: 用于生成此响应的请求对象。
template_name : 要使用的模板的全名或模板名称的序列。如果给定了序列,则将使用存在的第一个模板。有关如何查找模板的详细信息,请参阅模板加载文档。
可选参数(渲染到html的元素)
context 要添加到模板上下文中的值的字典。默认情况下,这是一个空字典。如果字典中的某个值是可调用的,则视图将在呈现模板之前调用它。 content_type 用于生成的文档的 MIME 类型。缺省值为 。'text/html' status 响应的状态代码。缺省值为 。200 using 用于加载模板的模板引擎的名称。
例如:我的工程叫book,有bookmanage和booktestone两个app
首先在工程同级目录建立一个testplate(用来存放前端文件),注意是工程同级别目录,而不是工程上一级目录,不然会找不到
在template下再建立对应的app目录,存放对应的app的前端文件
-
settings.py(添加前端模板位置):
-
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], # 配置模板位置 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
- 可以把这一堆字段串全都写到视图中, 作为
HttpResponse()
的参数,响应给客户端.
-
-
booktestone/urls.py :
-
from django.urls import path from django.urls import path,include from .views import index urlpatterns = [ path('index/', index ), ]
-
- booktestone/views.py
-
from django.shortcuts import render from django.http import HttpResponse, HttpRequest # Create your views here. def index(request): context = {'name': '我是模板渲染的参数'} return render(request,"booktestone/index.html", context ) #指定渲染的模板并传递模板参数
-
- template/index.html
- 渲染是将传递的context中的内容渲染
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> This is booktestone/index<br/> {{ name }} # 渲染取值是取context中的值 </body> </html>
- 前端访问展示
1.2例子
1.创建模板
- 在
应用
同级目录下创建模板文件夹templates
. 文件夹名称固定写法. - 在
templates
文件夹下, 创建应用
同名文件夹. 例,Book
-
在
应用
同名文件夹下创建网页模板
文件. 例 :index.html
-
2.设置模板查找路径
3.模板接收视图传入的数据
视图模板加载
4.模板处理数据
5. 查看模板处理数据成果
setting.py中得静态文件(图片之类得)
需要在setting.py中配置
# 告知静态文件在那里 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'目录名') ]
二、
错误之forbbiddon
csrf_token:这个标签用于跨站请求伪造保护
提交数据的时候就会做安全机制,当你点击提交的时候会出现一个forbbiddon 的错误,就是用setting配置里的scrf做安全机制的,那么我们可以吧它给注释了,,, 或者在form表单下面添加一个{% csrf_token %},,, 这才是真正解决的办法,注释不是解决的办法
<h3>scrf_token</h3><form action="/tag/" method="post"> {% csrf_token %} <p><input type="text" name="haiyan"></p> <input type="submit"> </form>
模型层又是Django创建之初自带的文件夹
里面是存放我们的HTML代码的 这样式为了便于维护 和增强解耦性
页面的设计和Python的代码分离开会更干净简洁更容易维护。 我们可以使用 Django的 模板系统 (Template System)来实现这种模式
python的模板:HTML代码+模板语法
模版包括在使用时会被值替换掉的 变量,和控制模版逻辑的 标签。
模板之---------深度查询:
它的深度查询式根据 .来区别的
<h1>深度查询</h1> <p>{{ name }}</p> <p>{{ l }}</p> {# 把views与之对应l显示在页面中#} <p>{{ info }}</p> {# 把views与之对应的info显示在页面#} <p>{{ l.0 }}</p> {#把l这个列表中的第一项显示出来 #} <p>{{ l.1 }}</p> {# 把l这个列表中的第二项显示出来#} <p>{{ l.2 }}</p> {# 把l对应的列表的第三项显示出来#} <p>{{ info.name }}</p> {#把字典info对应的name显示在页面中#}
所以看出来 深度查询就是利用点来查找具体的深度的值
模板之---------过滤器:
模板语法之过滤器:语法 {{obj|filter__name:param}}
1、default:
如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如:
<p>default过滤器:{{ li|default:"如果显示为空,设置的解释性的内容" }}</p>
2、length:返回值的长度。它对字符串和列表都起作用。例如:
{{ value|length }}
如果 value 是 ['a', 'b', 'c', 'd'],那么输出是 4。
3、filesizeformat:
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如:
{{ value|filesizeformat }}
如果 value
是 123456789,输出将会是 117.7 MB
。
4、date:如果 value=datetime.datetime.now()
{{ value|date:"Y-m-d" }}
5、slice :切片
如果 value="hello world"
{{ value|slice:"2:-1" }}
6、truncatechars 截断
如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:要截断的字符数
例如:
<p>截断字符:{{ content|truncatechars:20 }}</p> <p>截断单词:{{ content|truncatewords:4 }}</p>
如果content是“I am is haiyan,how are you asd df dfgfdgdg?
输出结果: 截断字符:I am is haiyan,ho...
输出结果 :截断单词:I am is haiyan,how ...
7、safe
Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。比如:
value="<a href="">点击</a>" {{ value|safe}}
<p>{{ label }}</p> <!--为了安全系统会把标签变成字符串--> <p>{{ label|safe }}</p> <!--加上safe,确定你的数据是安全的才能被当成是标签-->
模板语法之标签:语法为 {% tag %}:
标签看起来像是这样的: {% tag %}
。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。
一些标签需要开始和结束标签 (例如{% tag %} ...
标签 内容 ... {% endtag %})。
1、for标签(注:循环序号可以通过{{forloop}}显示)
{% for item in 迭代对象 %} 判读语句 {% endfor %}
if判读 {% if 条件 %} {% endif %}
for 语句
用
遍历每一个元素:
{% for person in person_list %} <p>{{ person.name }}</p> {% endfor %}
可以利用{% for obj in list reversed %}反向完成循环。
开始: {% for 加判读条件%} 结束 {%enfor%}
{% for item in l %} {% if item > 100 %} <p>{{ item }}</p> {% endif %} {% endfor %}
上面是先循环视图内的l列表 当列表内的item是大于100的那就打印在浏览器上
{% for animal in animal_list %} <p>{{ animal.name }},{{ animal.age }}</p> {% endfor %} 这个是打印你的视图内的animal_list列表内的对象的各个名字和年龄
循环序号可以通过{{forloop}}显示
{% for fool in l %} <p>{{ forloop.counter }}:{{ fool }}</p> {% endfor %} 就是把列表l的内容都循环输出 然后在它的开头给定义一个序列号 从1开始的序列号
for....empty :for 标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
{% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
if循环语句:
{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
其实和for语句差不多 都有开始 和结束 还有else
{% if animal.age > 30 %} <p>{{ animal.name }},{{ animal.age }}老年人</p> {% else %} <p>{{ animal.name }},{{ animal.age }}年轻人</p> {% endif %} 如果年龄大于30的就输出老年人 如果年龄小于30的就输出年轻人
with:使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的
其实就是起了一个别名
{% with total=business.employees.count %} {{ total }} employee{{ total|pluralize }} {% endwith %}
<p>{{ person_list.2.name }}</p> {% with name=person_list.2.name %} <p>{{ name }}</p> {% endwith %}
{% with f_name=animal_list.0.name %} <p>{{ f_name }}</p> {% endwith %} 给列表中的第一个name起一个别名
就是起别名