模板用于快速生成动态页面返回给客户端,模板是一个文本,用于分离文档的表现形式和内容.模板定义了占位符以及各种用于规范文档该如何现实的模板标签.模板通常用于产生html,但是django的模板也能产生任何基于文本格式的文档.模板包含两个部分:
- html代码
- 模板标签
一、模板位置
-
在应用中建立templates目录,有多个应用的时候不能复用页面
-
第二种是放在工程的目录下,好处是如果有多个应用,可以调用相同的页面,需要注册
-
需要修改项目的配置文件
settings.py
-
TEMPLATES = [ { 'BACJEND':'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', ] } } ]
-
二、模板的渲染
-
loader加载
好处是可以加载一次模板,然后进行多次渲染
from django.template import loader def index(request): temp = loader.get_template('index.html') print(temp.__dict__) # 渲染模板生成HTML源码 res = temp.render(context={'content':'hello world'}) print(res) return HttpResponse(res)
-
render
from django.shortcuts import render def index(request): return render(request,templatename,context=None)
三、模板语法
Django
模板中包含两个部分:变量和内置标签.变量会在模板渲染时被其值代替,内置标签负责逻辑控制.
1. 变量
变量在模板中表示:{{变量名}},变量名就是render中context中的键. 变量可以是基本类型中的数值,string,boolean,也可以是directory,object,list等. Django
提供了点号来访问复杂的数据结构
- 列表,元组的元素可以使用索引引用,不能使用负索引, 语法: 变量.index
- 字典: 字典变量.key
- 对象: 对象.属性 对象.方法名 (方法不能有参数)
当模板系统在变量名中遇到点的时候,按照以下顺序进行查找:
- 字典类型查找
- 属性方法查找
- 方法调用
- 列表类型索引
如果模板中引用变量未传值,则会被置为空,不会报错,除非你对其进行了其他操作
2. 过滤器
过滤器是在变量显示之前修改它的值的一个方法,过滤器使用管道符,可以串联使用
{{ 变量 | 方法 | 方法2 … }}
- 常见过滤器方法:
方法名 | 作用 | 示例 |
---|---|---|
default | 缺省值 | {{ li | default:“缺省值” }} |
default_if_none | 如果缺省值是none,则显示缺省值 | {{ value | default_if_none: ‘hello’ }} |
cut | 从字符中删除指定字符 | {{ value | cut: ‘’ }} 删除value所有空格 |
length | 获取字符串或列表的长度 | |
lower | ||
upper | ||
truncatechars | 截取字符串前n个字符 | {{ value| truncatechars: 9 }} |
date | 格式化日期字符串 | {{ value| date : “Y-m-d H-i-s” }} |
add | 添加变量的值 | {{ num | add: “3” }} |
divisibleby | 把变量的值除以指定值 | |
first | 列表第一个元素 | |
last | 列表最后一个元素 | |
join | 将列表内容连接成一个字符串 | {{ value| join: ‘-’ }} |
autoescape | 设置或取消转义 | { % autoescape off %} {{ data }} {% endautoescape %} |
-
自定义过滤器
-
在app包里创建一个包: templatetags
-
在包里创建一个py文件
from django import template # 实例化自定义过滤器注册对象 register = template.Library() # name代表在模板中使用的过滤器的名称 @register.filter(name='xxx') def send_time(value,arg): """ :param value: :return: 1. 如果时间间隔小于1min内,那么显示刚刚 2. 如果时间间隔大于1min小于1hour,那么显示xx分钟前 3. 如果时间间隔大于1hour小时24小时,显示xx小时前 4. 如果时间间隔大于24小时小于30天,显示xx天前 5. 如果时间大于30天,那么显示具体时间 """ if not isinstance(value,datetime.datetime): return value now = datetime.datetime.now() timestamp = (now-value).total_seconds() if timestamp<60: return "刚刚" elif timestamp>=60 and timestamp< 60*60: return '{}分钟前'.format(timestamp /60) elif timestamp >= 60*60 and timestamp<60**2*24: return '{}小时前'.format(timestamp/(60**2)) elif timestamp>=60**2*24 and timestamp<60**2*24*30: return '{}天前'.format(timestamp/(60**2*24)) else: return values.strftime('%Y-%m-%d %H:%M:%S')
-
在模板中使用
{% load customfilter %} # 加载自定义过滤器的模块 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ name | send_time :' how are you' }} #使⽤⾃定义过滤器 </body> </html>
-
3. 内置标签
语法: {% tag %}
-
1 if 标签
-
2 for标签
变量名称 | 变量说明 |
---|---|
forloop.counter | 过去迭代的索引 从1开始 |
forloop.counter0 | |
forloop.revcounter | |
forloop.revcounter0 | |
forloop.first | 是否为第一次迭代 |
forloop.last | 是否为最后一次迭代 |
forloop.parentloop | 获取上层迭代对象 |
-
3 ifequal/ifnotequal 用于判断两个值是否相等
{% ifequal/ifnotequal value value %}{% endifequal/endifnotequal%}
-
4 注释
- 单行注释 {# 注释的内容 #}
- 多行注释 {% comment %}…{% endcomment %}
-
5 跨站请求伪造
csrf
防止网站受第三方服务器的恶意攻击(确定表单是不是本网站的表单传递过来的).
csrf
相当于在表单中添加了一个而隐藏input表单域,用于向服务器提交一个唯一的随机字符串用于服务器验证表单是否是本服务器的表单.使用:
# settings.py MIDDLEWARE = [ 'django.middleware.csrf.CsrfViewMiddleware', ]
<form action='' method='post'> {% csrf_token %} <input type='text' name='username'> <p><input type='submit' value='提交'></p> </form>
-
全站禁用
csrf
只要将settings里的中间键注释就可以了
-
局部禁用
csrf
# 在不想检验csrf的视图函数前添加装饰器@csrf_exempt from django.view.decorators.csrf import csrf_exempt,csrf_protect @ csrf_exempt def csrf1(request): pass
-
Ajax
验证csrf
Ajax
提交数据的时候,携带CSRF
:a. 放置在data中携带:
<form method="POST" action="/csrf1.html"> {% csrf_token %} <input id="username" type="text" name="username" /> <input type="submit" value="提交"/> <a οnclick="submitForm();">Ajax提交</a> </form> <script src="/static/jquery-1.12.4.js"></script> <script> function submitForm(){ var csrf = $('input[name="csrfmiddlewaretoken"]').val(); var user = $('#user').val(); $.ajax({ url: '/csrf1.html', type: 'POST', data: { "user":user,'csrfmiddlewaretoken': csrf}, success:function(arg){ console.log(arg); } }) } </script>
csrf
的意义在于 给每⼀个表单都设置⼀个唯⼀的csrf
的值 并且cookie也存储⼀份 当提交表单过来的时候 判断cookie中的值 和csrf_token
中的值 是否都为本⽹站⽣ 成的 如果验证通过则提交 否则 403
-
-
6 模板中导入标签 include
{% include ‘路径/xxx.html’ %}
-
7 url标签
在模板中
url
标签可用于反向解析<h2> <a href='{% url "App:index" % }'>动态生成路由地址不带参数的跳转</a> </h2> <h2> <a href='{% url "App:args1" 1 2 %}'>动态生成路由带参数的跳转</a> </h2> <h2> <a href='{% url "App:args1" num1=1 num2=2 %}'>动态生成路由地址带关键字参数的跳转</a> </h2>
四、 模板继承
- {% extend ‘base.html’%} 继承父模板
- {% block %} 子模版可以重载这个部分内容
- {{ block.super }}
五、静态资源配置
什么是静态资源: css
,js
,images
… 需要从外部导入的资源
-
创建static文件夹(通常放在根目录下)
-
需要在settings中注册
STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'static'), ]
-
在模板中使用静态资源
{% load static %} # 放置到模板的开头 <img src='/static/img/img.png' alt=''> # 硬编码 <img src='{% static "img/img.png" %}' alt=''> # 动态写法,建议使用
六、jinja2
模板引擎配置
-
安装
jinja2
模板引擎pip install jinja2
-
配置
jinja2
环境变量# 在应用的目录下,创建一个jinja2_env.py 配置文件 from django.contrib.staticfiles.storage import staticfiles_storage from django.urls import reverse from jinja2 import Environment def enviroment(**options): env = Environment(**options) env.globals.update({ 'static':staticfiles_storage.url, 'url':reverse, }) return env
-
配置(settings.py)
-
独立使用
jinja2
,不使用Django
模板引擎# 独立使用jinja2 INSTALLED_APPS = [ # 'django.contrib.admin', # 注释了admin # ..... ] # 模板配置 TEMPLATES = [ { # 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.jinja2.Jinja2', # 设置为jinja2模板 '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', ], 'environment':'App.jinja2_env.environment', # 配置环境,jinjia2的配置文件位置 }, }, ]
-
两个共同使用
# 模板配置 TEMPLATES = [ { 'BACKEND': 'django.template.backends.jinja2.Jinja2', # 设置为jinja2模板 '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', ], 'environment':'App.jinja2_env.environment', # 配置环境,jinjia2的配置文件位置 }, }, { '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', ], }, }, ]
-
静态资源和
url
<p> <a href='{{ url('app:index')}}'>dddd</a> </p> <img src='{{ static("images/1.jpg")}}' alt=''>
-