Django之模板引擎(母版)
母版:存放所有页面的基本信息,基本样式
子班:继承母版
自定义当前页面私有的样式信息
母版的样式:
{% block xxx(名称) %} xxxxxxx(数据) {% endblock %}
例如:layout.html 是母版
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css" /> <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css" /> <link rel="stylesheet" href="/static/css/commons.css" /> {% block css %} {% endblock %}**** //这就是母版 <style> body{ margin: 0; } .pg-header{ height: 48px; min-width: 900px; background-color: #2b669a; } </style> </head> <body> <div class="pg-header"> <div class="logo left">学员后台管理</div> <div class="avatar right" style="position: relative"> <img style=" 40px;height: 40px;" src="/static/images/1.jpg"> <div class="user-info"> <a>个人资料</a> <a>注销</a> </div> </div> <div class="rmenus right"> <a><i class="fa fa-commenting-o" aria-hidden="true"></i> 消息</a> <a><i class="fa fa-envelope-o" aria-hidden="true"></i> 邮件</a> </div> </div> <div class="pg-body"> <div class="menus"> <a><i class="fa fa-futbol-o" aria-hidden="true"></i>班级管理</a> <a href="/students/">学生管理</a> <a>老师管理</a> <a>老师任课班级管理</a> </div> <div class="content"> <ol class="breadcrumb"> <li><a href="#">首页</a></li> <li><a href="/classes/">班级管理</a></li> <li class="active">添加班级</li> </ol> {% block way %} {% endblock %} ****//这就是母版, </div> </div> {% block js %} {% endblock %} ****//这就是母版 </body> </html>
子版的样式:
{% extends ‘xxx.html’ %} 继承xxx.html中的样式,xxx.html就是母版的样式
例如:classes.html 就是套用里母版
{% extends "layout.html"%} //继承母版 {% block css %} //这是写子版自己的样式 <style> .hide{ display: none; } .shadow{ position: fixed; left: 0; top: 0; right: 0; bottom: 0; background-color: black; opacity: 0.4; z-index: 999; } .addModal11{ z-index: 1000; position: fixed; left: 50%; top: 50%; height: 300px; width: 400px; background-color: white; margin-left: -200px; margin-top: -150px; } </style> {% endblock %} {% block way %} //这是套用母版样式的地方,显示自己样式的数据 <div> <div style="margin: 15px 0;"> <a class="btn btn-primary" href="/add_class/">添加</a> <a class="btn btn-primary" onclick="showModal();">对话框添加</a> <a class="btn btn-primary" href="/index/">返回</a> </div> <table class="table table-striped table-bordered table-hover"> <thead> <tr> <th>ID</th> <th>班级名称</th> <th>操作</th> </tr> </thead> <tbody> {% for item in class_lsit %} <tr> <td>{{ item.nid }}</td> <td>{{ item.title }}</td> <td> <a class="glyphicon glyphicon-trash" href="/del_class/?nid={{ item.nid }}"></a> | <a class="fa fa-edit" onclick="modelEdit(this);"></a> | <a class="glyphicon glyphicon-pencil" href="/edit_class/?nid={{ item.nid }}"></a> </td> </tr> {% endfor %} </tbody> </table> <div id="shadow" class="shadow hide"></div> <div id="modal" class="addModal11 hide"> <p>添加班级:<input id="title" type="text" name="title" placeholder="班级名称"></p> <input type="button" value="submit" onclick="AjaxSend();"/> <input type="button" value="cancel" onclick="cancleModal();"/><span id="errormsg"></span> </div> <div id="editModel" class="addModal11 hide"> <h3>编辑框</h3> <p> <input id="editId" type="text" name="nid" style=" display: none" /> <input id="editTitle" type="text" name="title" /> </p> <input type="button" value="submit" onclick="editAjaxSend();" /><span id="errormsg"></span> <input type="button" value="cancel" onclick="cancleModal();" /> </div> <script src="/static/jquery-1.12.4.js"></script> <script> function showModal() { document.getElementById("shadow").classList.remove("hide"); //找到遮罩层,并去挑遮罩层 document.getElementById("modal").classList.remove("hide"); } function cancleModal() { document.getElementById('shadow').classList.add('hide'); document.getElementById('modal').classList.add('hide'); document.getElementById('editModel').classList.add('hide'); } function AjaxSend(){ $.ajax({ url:'/modal_add_classes_ajax/', //往哪里提交 type:'POST', //以什么方式提交 data:{"title":$("#title").val()}, //拿到全段输入的值 success:function (data) { //当服务端处理完成后,返回数据时,该函数自动调用 //data是服务端返回的值 console.log(data); if(data=="ok"){ location.href='/classes/'; //指定提交成功后跳转到哪里 }else { $('#errormsg').text(data); } } }) } function modelEdit(ths) { document.getElementById("shadow").classList.remove("hide"); //找到遮罩层,并去挑遮罩层 document.getElementById("editModel").classList.remove("hide"); /* 1、获取当前点击标签 2、获取当前标签的父标签,再找其上方标签 3、获取当前行班级名称,赋值到编辑对话框中 */ var row = $(ths).parent().prevAll() //$(ths)是获取当前标签。 .parent是当前父标签。 .prevAll是当前级标签的上面所有的标签。 console.log(row); var content = $(row[0]).text(); //用列表取值的方式获取title。 .text是转成文本信息。 $('#editTitle').val(content); //找到title给他赋值给val里。 var contentId = $(row[1]).text(); $('#editId').val(contentId); } function editAjaxSend() { var nid = $('#editId').val(); //提交操作里前端获取id var content = $('#editTitle').val(); // 提交操作,前端获取新输入的值 console.log(nid,content); $.ajax({ url:'/modal_edit_classes_ajax/', type:"POST", data:{"nid":nid,"content":content}, success:function (arg) { // arg字符串类型 // JSON.parse(字符串) => 对象 // JSON.stringify(对象) => 字符串 arg = JSON.parse(arg); if(arg.status){ //location.href="/classes/" //这个是跳转 location.reload(); //这个是刷新 }else{ alert(arg.message); } } }) } </script> </div> {% endblock %}
在母版中有 {% block xxx(名称) %} xxxxxxx(数据) {% endblock %}
在子版中的block中的数据会去替换母版的数据,但是母版的格式依旧。
黄标为母版,这个编辑页面的样式,继承母版。
绿和红标,为继承的代码块
模板补充:
在后端传输字典类型的数据时,前端如何分别拿取key和value。
def test11111111(request): return render(request,"test11111.html",{ "userinfo":{"k1":"v1","k2":"v2"} })
方式1:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> {% for item in userinfo.values %} <h6>{{ item }}</h6> {% endfor %} </body> </html>
方式1的结果:
方式2:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> {% for k,v in userinfo.items %} <h6>{{ k }}---{{ v }}</h6> {% endfor %} </body> </html>
方式2的结果:
如果给前端传一些值改如何:
def test11111111(request): return render(request,"test11111.html",{"name":"george"})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> {{ name }} </body> </html>
结果:
但如果想要george变大写改如何操作呢?方式有两种:
其一:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> {{ name|upper }} </body> </html>
这个upper的本质是一个带装饰器的函数.
他是拿到一个value,并将value.upper操作的。而这个value就是我们后端传的name。
其二:自定义模板函数 simple_filter
这个simple_filter的创建一个分为三步。
a:在app中创建templatetags模块
b:创建一个任意的py文件,比如:xx.py,并存放我们要用的自定义函数
from django import template register = template.Library() # 这个别名必须叫register @register.filter def my_upper(value): return value.upper()
c:在HTML的文件顶部加上 {% load xx %} xx是在templatetags里创建的py文件。
{% load xx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> {{ name|my_upper }} </body> </html>
针对第二步的py文件,是可以丰富其功能的。
加参数:filter只支持两个参数,并且只支持前后各一个的。再多就不行啦。
from django import template register = template.Library() # 这个别名必须叫register @register.filter def my_upper(value,arg): return value + arg
{% load xx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> {{ name|my_upper:"666" }} // my_upper 后加冒号之后的就是第二个的参数,注意:冒号后不能有空格。 </body> </html>
tag的用法:
from django import template register = template.Library() # 这个别名必须叫register @register.filter def my_upper(value,arg): return value + arg @register.simple_tag() def my_lower(value): return value.lower()
{% load xx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> <h3>filter</h3> {{ name|my_upper:"666" }} <h3>tag</h3> {% my_lower "GEORGE" %} // my_lower 后有一个空格在 </body> </html>
加多个参数:
from django import template register = template.Library() # 这个别名必须叫register @register.filter def my_upper(value,arg): return value + arg @register.simple_tag() def my_lower(value,a1,a2,a3): return value + a1 + a2 + a3
{% load xx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> <h3>filter</h3> {{ name|my_upper:"666" }} <h3>tag</h3> {% my_lower "GEORGE" "--" "N" "B" %} </body> </html>
但是filter在参数上不如tag,可是filter可以用if判断,filter可以作为条件语句,放在if后面。而tag就不行。
from django import template register = template.Library() # 这个别名必须叫register @register.filter def my_upper(value,arg): return value + arg @register.simple_tag() def my_lower(value,a1,a2,a3): return value + a1 + a2 + a3 @register.filter def my_bool(value): return False
{% load xx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>打印字典所有的key</h2> <h3>filter</h3> {{ name|my_upper:"666" }} {% if name|my_bool %} <h6>真</h6> {% else %} <h6>假</h6> {% endif %} <h3>tag</h3> {% my_lower "GEORGE" "--" "N" "B" %} </body> </html>
在模板中也有include的概念:
在模板中的include的就是导入组件的功能。
在购物或社交的网址中,会有一些类似广告位的连接,以图片或图标的形式展示,他的位置固定,但内容可变。
include的小组件可以一个页面导入多个。
在template里创建一个pub.html。
<div>
<h3>特别漂亮的组件</h3> <div class="title">标题</div> <div class="content">内容</div> </div>
在目标页面加:
{% load xx %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include "pub.html" %} {% include "pub.html" %} {% include "pub.html" %} <h2>打印字典所有的key</h2> <h3>filter</h3> {{ name|my_upper:"666" }} {% if name|my_bool %} <h6>真</h6> {% else %} <h6>假</h6> {% endif %} <h3>tag</h3> {% my_lower "GEORGE" "--" "N" "B" %} </body> </html>
结果,这个include可以加多个。
如果在pub.html的页面里,也可以拿后端传的的参数。
<div> <div class="title">标题:{{ name }}</div> <div class="content">内容:{{ name }}</div> </div>
这个name就是后端return的name的值。将pub用include的方式加到目标页面,就可以显示了。
------- END -------