一、前言
mako最大的特点就是允许在HTML中随意书写Python代码,挺起就很心动啊!!
二、准备阶段
新建一个项目mako_project,再新建一个app叫app,然后安装mako(要联网安装)
pip install mako
然后再注册app,配置templates,还有static文件,这里就不赘述了。
实际上在配置mako时,并不需要对settings做特别的处理,主要是对render的处理,要重写一下render方法。
在app文件夹下创建一个base_render.py
写入以下代码:
#coding:utf-8from mako.lookup import TemplateLookup # 引入配置文件
from django.template import RequestContext
from django.conf import settings # 把django的settings引入进来
from django.template.context import Context
from django.http import HttpResponsedef render_to_response(request, template, c=None): # 考虑到可能要传入一些参数,这里加一个c,默认是空context_instance = RequestContext(request) # 一个实例path = settings.TEMPLATES[0]['DIRS'][0] # 把settings中的TEMPLATES引入,因为TEMPLATES是个数组,我们只需要取[0]就可以了# TEMPLATES[0]是一个字典,取出key = 'DIRS' 的value,是一个列表,然后再取[0],就是templates的地址了lookup = TemplateLookup(directories=[path],output_encoding='utf-8',input_encoding='utf-8') # template的目录就是path,再设置一下输入输出格式,都是utf-8mako_template = lookup.get_template(template) # 把模板导入if context_instance: # 判断实例是否存在context_instance.update(c)else:context_instance = Context(c) # 如果没有上下文,就在这里创建,并把需要的数据传入data = {}for d in context_instance:data.update(d)# 创建csrf_token,mako里不会自带data['csrf_token'] = '<input type="hidden" name="csrfmiddlewaretoken" value="{0}" />'.format(request.META['CSRF_COOKIE'])return HttpResponse(mako_template.render(**data))
view.py中
#coding:utf-8from django.views.generic import View
from .base_render import render_to_responseclass Test(View):TEMPLATE = 'test.html'def get(self, request):return render_to_response(request, self.TEMPLATE)
然后在urls中注册路由
from app.views import Testurlpatterns = [path('admin/', admin.site.urls),path('test/', Test.as_view())
]
运行一下,报错了。
other_dict must be a mapping (dictionary-like) object.
主要问题就出现在参数 c 上:context_instance.update(c)
,c需要是个字典,所以我们可以判断一下,如果c是空的话,就让c = 一个空字典{}。不建议在定义函数那里就让c是一个空字典,会有安全隐患。
if not c:c = {}
三、Mako模块的编写
在views中加入数据
def get(self, request):data = {'name': 'cong', 'age': 18}return render_to_response(request, self.TEMPLATE, data)
mako中HTML的书写格式就不同了,这里是**${}**
mako的厉害之处就是可以完全使用Python语言:
<%!from django.conf import settings%>${settings.TEMPLATES[0]['DIRS'][0]}
这个地址就被拿过来了。
不过依旧要%for %endfor 。。。
再写个for循环
%for i in range(20):<input type="text" value="${i}" />
%endfor
还可以自己写一个函数
<%def name():return 'my name is cong'
%><input style="display:block" type="text" name="username" value="${name()}" />
依旧可以继承模板
所有的模板继承都是以函数的形式进行的。
这里self. 是表示这个函数是在当前的HTML里面的。
还可以嵌套调用函数
注意:定义完之后,一定要再调用一下函数才可以使用哦!
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>${self.title()}</title>
</head>
<body>${self.content()}${self.js()}
</body>
</html>
<%def name="content()">${self.main()}
</%def>
<%def name="main()"></%def>
<%def name="title()"></%def>
<%def name="js()"></%def>
<%def name="css()"></%def>
如何在html中继承:
<%inherit file="base.html" />
使用模板
<%def name="main()">
<h1>hello mako</h1>
</%def>
<%inherit file="base.html" /><%def name="main()">
<h1>hello mako</h1>
</%def><%def name="js()">
<script src="https://cdn.bootcss.com/jquery/2.2.0/jquery.js"></script></%def>
<%def name="title()">test...dazzy</%def>
在html中调用函数的顺序随意,函数的位置是按照base模板定义的来确定。
四、HTML嵌套,以及传值
新建一个extend.html文件
<%page args="local_content" /><textarea>${local_content}
</textarea>
通过这种方式,就可以在其他页面找到一个local_content,然后把值传入进来,再显示出来。
然后在index.html的main函数中,给local_content传入值:
<%def name="main()">
<%include file="extend.html" args="local_content='你好 mako'" /><h1>hello mako</h1>
</%def>
使用情景:发布信息时,许多HTML文件中都要用到,不同HTML传过来的文件也不一样。
这样就可以公用一个HTML模板,并且随意传入值。
五、静态文件导入
static文件夹下新建test.css
* {background-color: pink;
}
html中
<%def name="css()">
<link rel="stylesheet" href="/static/test.css" />
</%def>
如果有公用的css文件,就可以在base.html中直接传入进去。
通过继承base模板,每个HTML就都会有最原始的css样式了。