zoukankan      html  css  js  c++  java
  • Django的模板层简介

    Django的模板层

    如果我们想要利用视图函数返回一个页面,一种比较简单的方式是利用HttpResponse()方法返回一个含有html内容的字符串:
    def current_datetime(request):
        now = datetime.datetime.now()
        html = "<html><body>It is now %s.</body></html>" % now
        return HttpResponse(html)
    
    尽管这种方式可以十分方便的解释视图的工作方式,但是,直接将HTML硬编码到你的视图里却并不是一个好主意。原因如下:
    1.对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 站点设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。
    2.Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。
    3.程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。
    基于上述原因,将页面的设计与Python代码分离开会干净简洁并且更易于维护。
    因此,我们需要使用Django的模板系统(Template System)来实现这种设计模式。

    Django的模板文件

    简单的讲,Django的模板文件其实就是HTML代码模板语法结合而成的一个“组合体”。
    这里我们还以“返回当前时间”的需求为例,这次我们用模板文件去做,视图函数中的内容为(这里略去路由部分):
    def index(request):
    	import datetime
    	n = datetime.datetime.now()
    	now = n.strftime('%Y-%m-%d %X')
    	return render(request,'index.html',{'time_now':now})
    
    模板文件index.html文件的内容为:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<meta charset="UTF-8">
    	<title>Title</title>
    </head>
    <body>
    
    <h4>当前时间:{{ time_now }}</h4>
    
    </body>
    </html>
    
    这里render()方法渲染的模板文件是index.html,而往模板文件传的参数是time_now这个键对应的key值now
    模板文件index.html中除了我们熟悉的html标签以外,多了一个模板语法:{{ time_now }}。接下来为大家详细介绍下模板的语法。

    Django的模板语法

    变量

    变量就是在Django模板中遍历复杂数据结构的句点字符,它的语法如下:{{ var_name }}
    这里的var_name与视图函数中返回的render方法的第三个参数(字典)中的'key'值相对应。也就是说,模板文件接收的“参数”都是经过视图函数处理后传来的,而且视图函数可以将任何类型的数据(数字、字符串、列表、字典、对象、类等等)传给模板。
    由于本文只讲解模板层的语法,因此下面的内容将路由控制与视图层的函数处理过程省略掉,但是建议大家在理解的时候尽量与路由控制与视图函数联系起来,因为这样有助于体会整个Django项目的“流程”。
    变量的深度查询我们用句点符.来完成。比如我们想取列表ls下标为0的元素:{{ ls.0 }}
    我们这里深入去研究变量的过滤器。所谓过滤器,其实就是对视图函数传来的值进行“加工”。过滤器的基本语法是:{{ obj|filter_name:param }}。其中obj为变量的名字;filter_name为某一个过滤器的名字;param是相应过滤器的参数。
    各种常见的过滤器列举如下:
    (1)date:如果views.py文件中传给模板的是一个“时间戳”,我们需要对这个时间进行格式化,具体语法是:{{n|date:'Y-m-d'}}
    (2)default:如果一个变量是false或者为空,则使用给定的默认值。否则,使用变量的值。例如:{{value|default:'nothing'}}
    (3)length:返回值的长度。它对字符串和列表都起作用。例如:{{value|length}}
    (4)slice:切片,假如value为一个字符串,找到它下标为2-5切片组成的新字符串:{{value|slice:'2:5'}}
    (5)truncatechars:如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。参数是要截断的字符数。这里需要注意,结尾的'...'算三个字符,如果参数<=3,那浏览器上显示的永远是'...':{{value|truncatechars:5}}
    (6)safe:Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。比如views.py文件中的字符串是这样的:value="<a href="">点击</a>"那index.html中告诉浏览器正常渲染就行,最终得到的是一个a标签:{{value|safe}

    标签

    标签的语法是这种结构: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签,例如:
    {% tag %} 
    ...标签内容 ...
    {% endtag %}
    
    而标签的深度查询也跟变量一样,利用句点符来进行,这里主要介绍两种常见的标签:for标签if标签
    (1)for标签:它的作用是遍历每一个元素。比如我们想遍历一个字典:
    {% for key,value in dic.items %}
    <p>{{key}}:{{value}}</p>
    {% endfor %}
    
    (1-1)循环期间的编号可以用{{ forloop }}显示,一下是forloop的说明:
    forloop.counter            The current iteration of the loop (1-indexed)
    forloop.counter0           The current iteration of the loop (0-indexed)
    forloop.revcounter         The number of iterations from the end of the loop (1-indexed)
    forloop.revcounter0        The number of iterations from the end of the loop (0-indexed)
    forloop.first              True if this is the first time through the loop
    forloop.last               True if this is the last time through the loop
    
    例如我们想在遍历上面的字典时加上编号:
    {% for key,value in dic.items %}
    <p>{{forloop.counter0}}:{{key}}:{{value}}</p>
    {% endfor %}
    
    (1-2)for...empty:for标签带有一个可选的{% empty %} 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。
    {% for person in person_list %}
    <p>{{ person.name }}</p>
    {% empty %}
    <p>sorry,no person here</p>
    {% endfor %}
    
    (2)if标签:{% if %}会对一个变量求值,如果它的值是“True”(存在、不为空、且不是boolean类型的false值),对应的内容块会输出。
    {% if num > 100 or num < 0 %}
    	<p>无效</p>
    {% elif num > 80 and num < 100 %}
    	<p>优秀</p>
    {% else %}
    	<p>凑活吧</p>
    {% endif %}
    

    继承

    Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素并且可以定义能够被子模版覆盖的blocks 。
    也就是说你,我们可以将重复的“骨架”写到一个base文件中,如果其它的文件都是基于这个骨架来写的,那么我们可以在这个骨架中在需要修改的地方用模板语法“标注”,以便可以让其它文件去替换它。
    例如,我们在templates包中加入“骨架”文件base.html:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<link rel="stylesheet" href="style.css" />
    	<title>{% block title %}My amazing site{% endblock %}</title>
    </head>
    
    <body>
    	<div id="sidebar">
    		{% block sidebar %}
    		<ul>
    			<li><a href="/">Home</a></li>
    			<li><a href="/blog/">Blog</a></li>
    		</ul>
    		{% endblock %}
    	</div>
    
    	<div id="content">
    		{% block content %}{% endblock %}
    	</div>
    </body>
    </html>
    
    我们可以看到它定义了一个可以用于两列排版页面的简单HTML骨架。“子模版”的工作是用它们的内容填充空的blocks。在这个例子中,block标签定义了三个可以被子模版内容填充的block。blocks的作用是告诉模版引擎:子模版可能会覆盖掉模版中的这些位置。
    我们将其中的一个字模板命名为base1.html,这里省略路由控制与视图函数中的内容,文件的内容是:
    {% extends 'base.html' %}
    {% block title %} 哈哈哈哈 {% endblock %}
    {% block content %}
    	<p>{{ list_w }}</p>
    {% endblock %}
    
    extends标签是这里的关键。它告诉模版引擎,这个模版“继承”了另一个模版。当模版系统处理这个模版时:首先,它将定位父模版——在此例中,就是“base.html”;然后,模版引擎将注意到 base.html 中的三个 block 标签,并用子模版中的内容来替换这些block。
    根据child1.html文件中的内容,最终的输出看起来是这样的:
    <!DOCTYPE html>
    <html lang="en">
    <head>
    	<link rel="stylesheet" href="style.css" />
    	<title>哈哈哈哈</title>
    </head>
    
    <body>
    	<div id="sidebar">
    		<ul>
    			<li><a href="/">Home</a></li>
    			<li><a href="/blog/">Blog</a></li>
    		</ul>
    	</div>
    
    	<div id="content">
    		<p> [111,222,333]</p>
    	</div>
    </body>
    </html>
    
    这种方式使代码得到最大程度的复用,并且使得添加内容到共享的内容区域更加简单,例如,部分范围内的导航。但是需要注意的是,如果子模版并没有定义 sidebar block,所以系统最终会使用父模版中的值,也就是说,父模版的 {% block %} 标签中的内容总是被用作备选内容(fallback)。
    关于继承,还有一下提示需要大家注意:
    (1)如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
    (2)在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,
    	 你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
    (3)如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
    (4)为了更好的可读性,你也可以给你的{% endblock %} 标签一个 名字 。例如:
    		{% block content %}
    		...
    		{% endblock content %}
    在大型模版中,这个方法帮你清楚的看到哪一个{% block %}标签被关闭了。			
    (5)不能在一个模版中定义多个相同名字的block标签。
    
  • 相关阅读:
    图片上传-下载-删除等图片管理的若干经验总结3-单一业务场景的完整解决方案
    图片上传-下载-删除等图片管理的若干经验总结2
    HDU 1195 Open the Lock
    HDU 1690 Bus System
    HDU 2647 Reward
    HDU 2680 Choose the best route
    HDU 1596 find the safest road
    POJ 1904 King's Quest
    CDOJ 889 Battle for Silver
    CDOJ 888 Absurdistan Roads
  • 原文地址:https://www.cnblogs.com/paulwhw/p/9379869.html
Copyright © 2011-2022 走看看