模板的配置 1.编辑项目下的 settings.py 文件,在该文件中找到关键字 TEMPLATES = [...]
,修改其中的 DIRS
关键字后的值,指定模板文件存放的目录路径,比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 TEMPLATES = [ { 'BACKEND' : 'django.template.backends.django.DjangoTemplates' , 'DIRS' : [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' , ], }, }, ]
2.根据配置,在项目根目录下创建模板目录 templates:
3.接下来,我们就在创建的 templates 目录中创建前端 html 文件进行使用
模板的使用 为了便于测试,我们先去 ECHARTS 站点下载一个 html 文件,比如: line-stack.html,将其存放到上面创建的 templates 目录中:
1.编辑子应用下的视图文件 views.py,在最下面添加访问目录文件的视图函数 line_stack,内容如下:
1 2 3 def line_stack (request ): return render(request, 'line-stack.html' )
2.编辑子应用下的路由文件 urls.py ,在路由配置段 urlpatterns = [...]
中添加访问模板文件的路由,如下:
1 2 3 4 urlpatterns = [ ... path('line_stack/' , views.line_stack), ]
3.在浏览器中输入 django 访问地址:http://192.168.3.254:8001/users/line_stack/, 如下图:
模板语法 1.Django 模板方法是 Djang 模板语言中的一种语法结构,用于在模板中调用函数。 2.模板方法的语法是:
1 {{ function_name(argument1, argument2)|过滤器 }} 或 {{ 变量名|过滤器 }};
3.利用 render() 方法把后端的数据通过 context 参数以字典传参的形式(默认 ceontext 参数为空),将数据显示到前端 html;
以{{ user.uname }}为例
1 2 3 首先把 user 当成一个字典,把 uname 当成键名,即对user['uname' ]进行取值 把 user 当成一个对象,把 uname 当成属性,即对user.uname进行取值 把 user 当成一个对象,把 uname 当成对象的方法,即对user.uname()进行取值
再以{{ user.0 }}为例
1 2 首先把 user 当成一个字典,把 0 当成键名,即对user['0' ]进行取值 把 user 当成一个列表,把 0 当成下标,即对user[0 ]进行取值
如果解析失败,则产生内容时用空字符串填充模板变量
使用模板变量时,.前面的可能是一个字典,可能是一个对象,还可能是一个列表
列表类型数据 实例一:展示自定义在视图函数中的数据 比如,我们要修改模板文件 line-stack.html 中字典 xAxis: {...}
中 data 的值:[‘Mon’, ‘Tue’, ‘Wed’, ‘Thu’, ‘Fri’, ‘Sat’, ‘Sun’]
1.编辑子应用的视图文件 views.py,修改视图汉书 line_stack 为:
1 2 3 4 5 6 7 def line_stack (request ): data = { 'test' : ['礼拜一' , '礼拜二' ,'礼拜三' ,'礼拜四' ,'礼拜五' ,'礼拜六' ,'礼拜天' ] } return render(request, 'line-stack.html' , context=data)
2.编辑模板文件 line-stack.html ,修改字典 xAxis: {...}
中 data 的值为 模板语法,变量名为子视图文件 views.py 中定义的字典 key 名称:
1 2 3 4 5 6 7 8 ... xAxis: { type: 'category', boundaryGap: false, data: {{ test }} }, ...
3.刷新下浏览器,发现 url 访问正常,但是没有数据展示。F12 打开浏览器开发者模式,可以看到调试窗口有报错信息,如图:
4.此时,我们就需要使用模板中的过滤器 |safe
,如何使用呢?如下。继续修改模板文件,在修改的模板文件中的模板语法处加上过滤器即可,如下:
1 2 3 4 5 6 xAxis: { type: 'category', boundaryGap: false, // data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] data: {{ test|safe }} },
过滤器:|safe ,将字符串标记为安全,不需要转义。但是,要保证 views.py 传过来的数据绝对安全,才能用 safe。 Django 会自动对 views.py 传到HTML文件中的标签语法进行转义,令其语义失效。加 safe 过滤器是告诉 Django 该数据是安全的,不必对其进行转义,可以让该数据语义生效。
5.再次刷新浏览,就可以看到底部的名称变成了我们在视图函数中定义的字典 ‘test’ 对应的值中的内容了:
实例二:展示模型类中的数据 1.首先在子视图文件 views.py 中导入模型类,然后将模型类中的数据查询出来:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 ... from users.models import PeopleInfo... def line_stack (request ): list1 = [] quest = PeopleInfo.objects.all () for i in quest: list1.append(i.name) data = { 'quest' : list1[0 :7 ] } return render(request, 'line-stack.html' , context=data)
2.再次编辑模板文件 line-stack.html ,修改字典 xAxis: {...}
中 data 的值为 模板语法,变量名为子视图文件 views.py 中定义的字典 key 名称:
1 2 3 4 5 6 7 8 ... xAxis: { type: 'category', boundaryGap: false, data: {{ quest|fase }} }, ...
3.刷新下浏览器,如下图;
字符串、字典数据类型 1.编辑子应用下的视图文件 views,在最底部添加一个 template 的视图函数,内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def templates (request ): strs = 'python 教程' dics = {'name' : 'Leazhi' , 'Age' : 25 } lis1 = ['教程1' , '教程2' , '教程3' ] data = { 'strs' : strs, 'lis1' : lis1, 'dics' : dics } return render(request, 'template.html' , context=data)
2.编辑子应用下的路由文件 urls.py ,添加访问视图函数 template 的路由,如下:
1 2 3 4 5 ... urlpatterns = [ ... path('template/' , views.templates), ]
3.在模板目录 templates 目录创建一个模板文件,这里命名为 template.html ,内容为:
模板文件中的变量 strs、lis1 及 dics 都是后端在视图文件 views.py 中定义在 data 数据库中的 key 名称,而不是在 template 函数中定义的标量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > {{ strs|length }}<br > {{ lis1.0 }}<br > {{ dics.Age }}<br > </body > </html >
4.打开浏览器,访问视图函数如下图:
模板过滤器 upper 过滤器 upper 过滤器是将后端传入过来的小写转换成大写:
1.修改模板文件 template.html(其它都不用动),将其修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > {{ strs|upper }}<br > {{ lis1.0 }}<br > {{ dics.Age }}<br > </body > </html >
2.刷新下浏览器,如下图:
date 过滤器 格式:
1 Y-m-d H:i:s 返回 年-月-日 时:分:秒
1.编辑子应用下的视图文件 views.py, 导入 datetime 模块,然后修改视图函数 template 为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import datetime... def templates (request ): strs = 'python 教程' dics = {'name' : 'Leazhi' , 'Age' : 25 } lis1 = ['教程1' , '教程2' , '教程3' ] now = datetime.datetime.now() data = { 'strs' : strs, 'lis1' : lis1, 'dics' : dics, 'time' : now } return render(request, 'template.html' , context=data)
2.编辑模板目录下的 template.html 文件,将其修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > {{ strs|upper }}<br > {{ lis1.0 }}<br > {{ dics.Age }}<br > 此时此刻的时间为:{{ time }}<br > 今天的日期为:{{ time|date:"Y-m-d" }} </body > </html >
3.刷新浏览器,如下图:
filesizeformat 以更易读的方式显示文件的大小(如 1KB, 976.6 MB 等)
1.编辑子应用下的视图文件 views.py, 导入 datetime 模块,然后修改视图函数 template 为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import datetime... def templates (request ): strs = 'python 教程' dics = {'name' : 'Leazhi' , 'Age' : 25 } lis1 = ['教程1' , '教程2' , '教程3' ] nows = datetime.datetime.now() nums = 1024000000 data = { 'strs' : strs, 'lis1' : lis1, 'dics' : dics, 'time' : nows, 'nums' : nums, } return render(request, 'template.html' , context=data)
2.编辑模板目录下的 template.html 文件,将其修改为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > {{ strs|upper }}<br > {{ lis1.0 }}<br > {{ dics.Age }}<br > 此时此刻的时间为:{{ time }}<br > 今天的日期为:{{ time|date:"Y-m-d" }}<br > 后端传入的 nums 大小为 {{ nums }},经过 filesizformat 过滤器后的大小为 {{ nums |filesizeformat }} </body > </html >
3.刷新浏览器,如下图:
模板标签 1 2 3 4 5 标签语法:不同于模板语法,模板语法双 {} 号,而标签语法是单 {} {% 标签名 变量名 %} ... {% end标签名%}
实例: 1.编辑子应用目录下的视图文件 views.py, 导入模型类 BookInfo ,然后添加视图函数 temp_tags,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ... from users.models import BookInfo... def temp_tags (request ): books = BookInfo.objects.all () print (books) data = { 'books' : books } print (data) return render(request, 'temp_tags.html' , context=data)
2.编辑子应用下的路由文件 urls.py ,添加访问视图函数 temp_tags 的路由:
1 2 3 4 5 6 ... urlpatterns = [ ... path('temp_tags/' , views.temp_tags), ]
3.在模板目录下新建模板文件 temp_tags.html, 内容为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > {% for book in books %} {% if book.id <= 6 %} <li > 这本书的书名为:{{ book.id }}---->{{ book.name }}, 出版日期为 {{ book.pub_date}}</li > {% endif %} {% endfor %} </body > </html >
4.打开浏览器,访问 temp_tags:
模板的继承与应用 模板的继承是指前端的 html 内容继承,而不是后端的数据也继承(也就是说只继承父模板文件中的内容,如果父模板中有后端传入的数据则不会被继承)
现在,我的 template 目录下有 3 个 html 页面,分别为:register.html 、template.html 以及 line_stack.html 。现在的需求是:要 template.html 继承 line_stack.html,将 line_stack.html 上的内容在 template.html 上面显示。这个时候,我们就需要使用模板标签:
父模板文件中需要先使用下面的标签语法预区域,该区域留给子模板填充差异性的内容,不同预留区域名字不能相同:
1 2 3 {% block 标签名称<这个名称随意定义,子模板中需要调用>%} ... {% endblock %}
子模板中则使用下面的标签语法指定继承的父模板文件路径,
1 2 {% extends '继承的父模板文件路径' %}
且该标签必须放在模板文件中的首行。否则会报:
1 django.template.exceptions.TemplateSyntaxError: <ExtendsNode: extends 'line-stack.html' > must be the first tag in the template.
实例一:只在子模板中使用 extends ,而不在父模板中划区域的继承 1.先修改下父模板(因为我们上面父模板中有后端传入的数据,这里要还原回去):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 <!DOCTYPE html > <html lang ="zh-CN" style ="height: 100%" > <head > <meta charset ="utf-8" > </head > <body style ="height: 100%; margin: 0" > <div id ="container" style ="height: 100%" > </div > <script type ="text/javascript" src ="https://fastly.jsdelivr.net/npm/[email protected] /dist/echarts.min.js" > </script > <script type ="text/javascript" > var dom = document .getElementById ('container' ); var myChart = echarts.init (dom, null , { renderer : 'canvas' , useDirtyRect : false }); var app = {}; var option; option = { title : { text : 'Stacked Line' }, tooltip : { trigger : 'axis' }, legend : { data : ['Email' , 'Union Ads' , 'Video Ads' , 'Direct' , 'Search Engine' ] }, grid : { left : '3%' , right : '4%' , bottom : '3%' , containLabel : true }, toolbox : { feature : { saveAsImage : {} } }, xAxis : { type : 'category' , boundaryGap : false , data : ['Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' , 'Sun' ] }, yAxis : { type : 'value' }, series : [ { name : 'Email' , type : 'line' , stack : 'Total' , data : [120 , 132 , 101 , 134 , 90 , 230 , 210 ] }, { name : 'Union Ads' , type : 'line' , stack : 'Total' , data : [220 , 182 , 191 , 234 , 290 , 330 , 310 ] }, { name : 'Video Ads' , type : 'line' , stack : 'Total' , data : [150 , 232 , 201 , 154 , 190 , 330 , 410 ] }, { name : 'Direct' , type : 'line' , stack : 'Total' , data : [320 , 332 , 301 , 334 , 390 , 330 , 320 ] }, { name : 'Search Engine' , type : 'line' , stack : 'Total' , data : [820 , 932 , 901 , 934 , 1290 , 1330 , 1320 ] } ] }; if (option && typeof option === 'object' ) { myChart.setOption (option); } window .addEventListener ('resize' , myChart.resize ); </script > </body > </html >
2.编辑子模板,在子模板顶部添加继承:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 {% extends 'line-stack.html' %} <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > Title</title > </head > <body > 后端传入的 strs 值为 {{ strs}}, 经过过滤器 upper 后的数据为:{{ strs|upper }}<br > 后端传入的 lis1 值为 {{ lis1}}, 经过下标 0 取值后的数据为:{{ lis1.0 }}<br > 后端传入的 dics 值为 {{ dics }}, 通过字典 取 Age key 值后的值为:{{ dics.Age }}<br > 此时此刻的时间为:{{ time }}<br > 今天的日期为:{{ time|date:"Y-m-d" }}<br > 后端传入的 nums 大小为 {{ nums }},经过 filesizformat 过滤器后的大小为 {{ nums |filesizeformat }}<br > </body > </html >
3.刷新浏览器,如图: