作者:BerenCamlost
1 定义模板
1.1 变量
- 视图传递给模板的数据
- 要遵守标识符规则
- 语法
{{var}}
(var代表变量) - 【注意】:如果使用的变量不存在,则插入的是空字符串
- 在模板中使用点语法,点后边的东西按如下顺序进行匹配
- 字典查询
- 属性或者方法
- 数字索引
在模板中调用方法
- sunck/models.py:
# 插入到Students类中的方法
def get_name(self):
return self.sname
- sunck/views.py:
# templates 测试
def templates(request):
stu = Students.stuObj2.get(sname='刘德华')
return render(request, 'sunck/templates测试/templates1.html', {'stu': stu})
- sunck/urls.py:
path('template/', views.templates),
- sunck/templates测试/templates.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板测试</title>
</head>
<body>
<h1>{{ stu.get_name }}</h1>
<h1>{{ stu.sname }}</h1>
</body>
</html>
- 效果:
- 【注意】:在模板中调用方法时不能传递参数
1.2 标签
1.2.1 语法
{% tag %}
1.2.2 作用
- 在输出中创建文本
- 控制逻辑和循环
1.2.3 if
- 格式:
<!--if语句-->
{% if 表达式 %}
语句
{% endif %}
<!--else语句-->
{% if 表达式 %}
语句1
{% else %}
语句2
{% endif %}
<!--else if语句-->
{% if 表达式1 %}
语句1
{% elif 表达式2 %}
语句2
·
·
·
{% elif 表达式n %}
语句n
{% else %}<!--可有可无-->
语句e
{% endif %}
- 举例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模板测试</title>
</head>
<body>
<h1>{{ stu.get_name }}</h1>
<h1>{{ stu.sname }}</h1>
<h1>num={{ num }}</h1>
{% if num is 10 %}
<h2>You are a handsome boy</h2>
{% elif num is 20 %}
<h2>you are a Very handsome boy</h2>
{% else %}
<h2>You are not a handsome boy</h2>
{% endif %}
</body>
</html>
在Views.py中给num传一个数字,得到效果如下图所示:
1.2.4 for
{% for 变量 in 列表 %}
{#语句1#}
{% empty %}
{#语句2#}
{% endfor %}
- 【注意】:当列表为空或者不存在时,执行empty语句,empty可有可无
{{ forloop.counter }}
表示循环次数,可以用在for语句中,例如:
<ul>
{% for student in stu1 %}
{#语句1#}
<li>{{ forloop.counter }}:{{ student.sname }}---{{ student.scontend }}</li>
{% empty %}
{#语句2#}
<li>没有学生信息</li>
{% endfor %}
</ul>
- views.py文件中为:
def templates(request):
stu1 = Students.stuObj2.all()
# stu1 = Students.stuObj2.filter(sname__startswith="刘")
# stu1 = Students.stuObj2.filter(sname__startswith="Liu")
return render(request, 'sunck/templates测试/templates1.html', { 'stu1': stu1})
1.2.5 comment
- 格式
{% commnet %}
被注释的内容
{% endcomment %}
- 作用:相当于多行注释,被注释的内容不再执行
1.2.6 ifequal/ifnotequal
- 【作用】:判断是否相等或者不相等
- 【格式】:
{% ifequal 值1 值2 %}
语句1
{% endifequal %} # 如果值1等于值2,执行语句1,否则不执行语句1
1.2.7 include
- 【作用】:加载模板并以标签内的参数渲染
- 【格式】:
{% include '模板目录' 参数1 参数2 %}
1.2.8 url
- 【作用】:反向解析
- 【格式】:
{% url 'namespace: name' p1 p2 %}
1.2.9 csrf_token
- 【作用】:用于跨站请求伪造保护
- 【格式】:
{% csrf_token %}
1.2.10 block, extends
- 【作用】:用于模板的继承
1.2.11 autoescape
- 【作用】:用于HTML转义
1.3 过滤器
- 【语法】:
{{var|过滤器}}
- 【作用】:在变量被显示前修改它,只是加一个效果,对变量不会造成影响
1.3.1 upper/lower
- 大写和小写,示例:
{#5. 过滤器#}
<h1>原型:{{ str }}</h1>
<h1>upper:{{ str|upper }}</h1>
<h1>lower:{{ str|lower}}</h1>
- 【效果】:
1.3.2 过滤器可以传递参数
- 下面以
var|join:'str'
为例解释传参的过程:
# templates 测试
def templates(request):
stu1 = Students.stuObj2.all()
return render(request, 'sunck/templates测试/templates1.html', {'stu1': stu1,})
<h2>{{ stu1|join:"--的儿子是-->" }}</h2>
【效果】(涉及隐私我打了马赛克):
1.3.3 default默认值
- 如果一个变量没有被提供,或者值为false,空,我们可以通过 default 语法使用默认值
- 【示例】:
<h2>{{ stu1.sname|default:'啥都么的' }}</h2>
1.3.4 date
- 【作用】:根据给定格式转换日期为字符串
- 【示例】:
{{dateVal|date:'y-m-d'}}
以年月日的形式显示日期,dateVal
是一个日期变量
1.3.5 escape
- 【作用】:HTML转义
1.3.6 加减乘除
- 【示例】:
<ul>
<li>num:{{ num }}</li>
<li>num+10:{{ num|add:10 }}</li>
<li>num-5:{{ num|add:-5 }}</li>
<!--num/1*5-->
<li>num*5:{% widthratio num 1 5 %}</li>
<li>num/2:{% widthratio num 2 1 %}</li>
</ul>
- 效果:
1.3.7 给之前的学生列表加背景颜色
|divisibleby:2
:可被2整除
<ul>
{% for student in stu1 %}
{% if forloop.counter|divisibleby:2 %}
<li style="background-color: gray">{{ forloop.counter }}:{{ student.sname }}---{{ student.scontend }}</li>
{% else %}
<li style="color: orange">{{ forloop.counter }}:{{ student.sname }}---{{ student.scontend }}</li>
{% endif %}
{% empty %}
<li>没有学生信息</li>
{% endfor %}
</ul>
- 【效果】(打码真的费时间):
1.4 注释
- 【单行注释】:
{{# #}}
- 【多行注释】:
{%comment%}....{%endcomment%}
2 反向解析
2.1 作用
即使url变动,也可以根据namespace和name反向解析出正确的域名,从而实现超链接的正确执行。
2.2 示例
<a href="{% url 'sunck:good' %}">反解析连接good</a>
# project/project/urls.py
urlpatterns = [
path('sunck/', include('sunck.urls', namespace="sunck")),
]
# project/sunck/urls.py
urlpatterns = [
path('template/good/', views.good, name='good'),
]
2.3 传入参数
模板:
<a href="{% url 'sunck:good' 1 %}">反解析连接good</a>
url:
path('template/good/<int:id>', views.good, name='good'),
views视图:
# templates-反向解析 测试
def good(request, id):
return render(request, 'sunck/templates测试/good.html', {'num': id})
good模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>good</title>
</head>
<body>
<h1>good--{{ num }}</h1>
</body>
</html>
3 模板继承
3.1 作用
- 模板继承可以减少页面的重复定义,实现页面的重用
3.2 block标签
- 【作用】:在父模板中预留区域 ,子模板去填充
- 【语法】:
{% block 标签名 %}
...
{% endblock 标签名 %}
3.3 extends标签
- 继承模板,需要写在模板文件的第一行
- 【语法】:
{% extends 'myApp/base.html(父模板路径)' %}
{% block 标签名 %}
内容
{% endblock 标签名 %}
3.4 示例
- base.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>base</title>
</head>
<body>
<div id="header">
<h1>header</h1>
</div>
<div id="main">
{% block main %}
{% endblock main %}
</div>
<div id="footer">
<h1>footer</h1>
</div>
</body>
</html>
- main.html:
{% extends "sunck/模板继承/base.html" %}
{% block main%}
<h1>{{ 'main'|upper }}</h1>
{% endblock main %}
4 HTML转义
4.1 问题
# templates 测试
def templates(request):
return render(request, 'sunck/templates测试/templates1.html',
{
'str2': '<h1>HTML转义</h1>'
})
{#6 HTML转义#}
{{ str2 }}
- 这时的输出为
<h1>HTML转义</h1>
,未经过渲染,而我们想要的输出是HTML转义
4.2 解决
- 过滤器safe可以关闭转义,escape开启转义
- 标签
{% autoescape off %}...{% endautoescape %}
关闭自动转义,将off变成on开启自动转义
4.3 示例
- html文件:
{#6 HTML转义#}
{{ str2 }}
{{ str2|escape }}
{{ str2|safe }}
{% autoescape on %}
1{{ str2 }}
2{{ str2 }}
{% endautoescape %}
{% autoescape off %}
1{{ str2 }}
2{{ str2 }}
3{{ str2 }}
{% endautoescape %}
- 【效果】:
5 CSRF
5.1 跨站请求伪造
某些恶意网站包含链接,表单,按钮,js,利用登录用户在浏览器中认证,从而攻击服务
5.2 防止CSRF
- 在settings.py文件的
MIDDLEWARE
增加'django.middleware.csrf.CsrfViewMiddleware'
- 上述方法会将所有的跨站请求屏蔽,为了允许自身的跨站请求服务,应该在HTML页面中加入
{% csrf_token %}
,如:
<form action="../register/" method="post">
{% csrf_token %}
<!--这里的action需要和后面的urls路径相对应-->
姓名:<input type="text" name="name" value=""/>
<hr>
性别:<input type="radio" name="gender" value="1">男<input type="radio" name="gender" value="0">女
<hr>
年龄:<input type="text" name="age" value=""/>
<hr>
爱好:<input type="checkbox" name="hobby" value="power"/>权利<input type="checkbox" name="hobby" value="money">金钱<input type="checkbox" name="hobby" value="beauty">美女<input type="checkbox" name="hobby" value="Tesla">Tesla
<hr>
<input type="submit" value="注册">
</form>
6 验证码
6.1 作用
- 在用户注册,登录页面的时候使用,为了防止暴力请求,减轻服务器的压力
- 是防止CSRF的一种方式
6.2 源码及效果
- 请查看作者的另外一篇博客:用Python写一个自动生成简单验证码图片的程序
6.3 输入验证码
6.3.1 视图
def verifi_code(request):
return render(request, 'sunck/templates测试/verificationcode.html', )
# 展示结果
def show(request):
code = request.POST.get('code')
right_code = request.session['verification_code']
if code.upper() == right_code.upper():
return HttpResponse('对了!'+right_code)
else:
return HttpResponse('错了!'+code+'----'+right_code)
6.3.2 url
path('VerificationCode/code', VerificationCode.verification_code),
path('VerificationCode/', VerificationCode.verifi_code),
path('VerificationCode/show', VerificationCode.show, name='show'),
6.3.3 模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证码</title>
</head>
<body>
<h3>请输入验证码</h3>
<form method="post" action="{% url 'sunck:show' %}">
{% csrf_token %}
<input type="text" name="code" value=""/>
<img src="/sunck/VerificationCode/code">
<hr>
<input type="submit" value="登录"/>
</form>
</body>
</html>