MVC与MTV模型
一、MVC
Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的、松耦合的方式连接在一起,模型负责业务对象与数据库的映射(ORM),视图负责与用户的交互(页面),控制器接受用户的输入调用模型和视图完成用户的请求,其示意图如下所示:
二、MTV
Django的MTV模式本质上和MVC是一样的,也是为了各组件间保持松耦合关系,只是定义上有些许不同,Django的MTV分别是:
- M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。
- T 代表模板 (Template):负责如何把页面展示给用户(html)。
- V 代表视图(View): 负责业务逻辑,并在适当时候调用Model和Template。
- 除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template,MTV的响应模式如下所示:
Django的下载与基本命令
- 下载Django:pip3 install django==2.0.1
- 创建一个django project: django-admin.py startproject luffy
- 在mysite目录下创建应用:python manage.py startapp app01
- 启动django项目:python manage.py runserver 8080 我们访问:http://127.0.0.1:8080/时就可以看到:
一、文件介绍
- manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。
- settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
- urls.py ----- 负责把URL模式映射到应用程序。
静态文件
1
2
3
4
5
|
#在settings.py中: STATIC_URL = ‘/static/‘ STATICFILES_DIRS = ( os.path.join(BASE_DIR, ‘static‘ ), ) |
路由
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要为该URL调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于客户端发来的某个URL调用哪一段逻辑代码对应执行。
一、简单的路由配置
- 若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
- 不需要添加一个前导的反斜杠,因为每个URL 都有。例如,应该是^articles 而不是 ^/articles。
- 每个正则表达式前面的‘r‘ 是可选的但是建议加上。它告诉Python 这个字符串是“原始的” —— 字符串中任何字符都不应该转义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# 在urls.py中: from django.urls import path,re_path from app01 import views # 路由配置: 路径--------->视图函数 urlpatterns = [ path( ‘admin/‘ , admin.site.urls), #无名分组:捕获的值作为位置参数传递给视图函数 re_path(r ‘^articles/([0-9]{4})/$‘ , views.year_archive), #year_archive(request,‘2009‘) re_path(r ‘^articles/([0-9]{4})/([0-9]{2})/$‘ , views.month_archive), # month_archive(request,‘2009‘,‘12‘) re_path(r ‘^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$‘ , views.article_detail), # month_archive(request,‘2009‘,‘12‘,‘1‘),# month_archive(request,‘2009‘,‘12‘,‘13‘) #有名分组:捕获的值作为关键字参数传递给视图函数 re_path(r ‘^articles/(?P<year>[0-9]{4})/$‘ , views.year_archive), # month_archive(request, year=‘2005‘) re_path(r ‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$‘ , views.month_archive), # month_archive(request, year=‘2005‘, month=‘03‘) re_path(r ‘^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$‘ , views.article_detail), # month_archive(request, year=‘2003‘, month=‘03‘, day=‘03‘) ] |
二、分发
1
2
3
4
5
6
7
8
9
10
11
|
# 在urls.py中: from django.urls import path, re_path, include urlpatterns = [ path( ‘admin/‘ , admin.site.urls), # 分发 re_path(r "^app01/" , include( "app01.urls" )), re_path(r "^app02/" , include( "app02.urls" )), re_path(r "^" , include( "app01.urls" )), ] |
三、反向解析
获得URL 的最终形式,,对于不同层级,Django 提供不同的工具用于URL 反查:
- 在模板中:使用url 模板标签。
- 在Python 代码中:使用from django.urls import reverse
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
|
# 在urls.py中: from django.urls import path,re_path,include from app01 import views urlpatterns = [ path( ‘admin/‘ , admin.site.urls), # 反向解析 path( ‘login.html/‘ ,views.login,name = "Log" ), re_path(r ‘^articles/([0-9]{4})/$‘ , views.year_archive, name = ‘news-year-archive‘ ), ] # 在模板中:注意参数 """ <form action="{% url ‘Log‘ %}" method="post"></form> <a href="{% url ‘news-year-archive‘ 2012 %}">2012 Archive</a> <ul> {% for yearvar in year_list %} <li><a href="{% url ‘news-year-archive‘ yearvar %}">{{ yearvar }} Archive</a></li> {% endfor %} </ul> <!--多个参数--> <a href="{% url "n4" i1 i2 %}">编辑</a> """ #在views.py中: from django.urls import reverse from django.shortcuts import render,HttpResponse,redirect def redirect_to_year(request): # 无参 url = reverse( ‘Log‘ ) print (url) #有参 year = 2006 url99 = reverse( ‘news-year-archive‘ , args = (year,)) print (url99) return HttpResponse( ‘OK‘ ) |
四、名称空间
命名空间(英语:Namespace)是表示标识符的可见范围。一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。我们在开发项目时,会经常使用name属性反解出URL,当不小心在不同的app的urls中定义相同的name时,可能会导致URL反解错误,为了避免这种事情发生,引入了命名空间。
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
|
# 在urls.py中: from django.urls import path, re_path, include urlpatterns = [ path( ‘admin/‘ , admin.site.urls), # 分发 re_path(r "^app01/" , include( "app01.urls" )), re_path(r "^" , include( "app01.urls" )), # 两个应用中,URL 模式名字一样时: re_path(r "^app01/" , include(( "app01.urls" , "app01" ))), re_path(r "^app02/" , include(( "app02.urls" , "app02" ))), ] #app01中的urls.py from django.urls import path,re_path from app01 import views urlpatterns = [ re_path( "index/" ,views.index,name = "index" ) ] #app02中的urls.py from django.urls import path,re_path from app02 import views urlpatterns = [ re_path( "index/" ,views.index,name = "index" ) ] #app01中的views.py from django.shortcuts import render,HttpResponse from django.urls import reverse def index(reqeust): return HttpResponse(reverse( "app01:index" )) #app02中的views.py from django.shortcuts import render,HttpResponse from django.urls import reverse def index(reqeust): return HttpResponse(reverse( "app02:index" )) |
五、django2.0版的path
1、基本实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 在urls.py中: from django.urls import path, re_path from app01 import views urlpatterns = [ re_path( ‘articles/(?P<year>[0-9]{4})/‘ , views.year_archive), re_path( ‘article/(?P<article_id>[a-zA-Z0-9]+)/detail/‘ , views.detail_view), re_path( ‘articles/(?P<article_id>[a-zA-Z0-9]+)/edit/‘ , views.edit_view), re_path( ‘articles/(?P<article_id>[a-zA-Z0-9]+)/delete/‘ , views.delete_view), ] """ 1.函数 year_archive 中year参数是字符串类型的 2.三个路由中article_id都是同样的正则表达式,但是你需要写三遍,当之后article_id规则改变后,需要同时修改三处代码, 在Django2.0中,可以使用 path 解决以上的两个问题。 """ urlpatterns = [ path( ‘articles/2003/‘ , views.special_case_2003), path( ‘articles/<int:year>/‘ , views.year_archive), path( ‘articles/<int:year>/<int:month>/‘ , views.month_archive), path( ‘articles/<int:year>/<int:month>/<slug>/‘ , views.article_detail), ] |
2、基本规则
- 使用尖括号(<>)从url中捕获值。
- 捕获值中可以包含一个转化器类型(converter type),比如使用 捕获一个整数变量。若果没有转化器,将匹配任何字符串,当然也包括了 / 字符。
- 无需添加前导斜杠。
3、path转化器
Django默认支持以下5个转化器:
- str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
- int,匹配正整数,包含0。
- slug,匹配字母、数字以及横杠、下划线组成的字符串。
- uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
- path,匹配任何非空字符串,包含了路径分隔符
4、注册自定义转化器
对于一些复杂或者复用的需要,可以定义自己的转化器。转化器是一个类或接口,它的要求有三点:
- regex 类属性,字符串类型
- to_python(self, value) 方法,value是由类属性 regex 所匹配到的字符串,返回具体的Python变量值,以供Django传递到对应的视图函数中。
- to_url(self, value) 方法,和 to_python 相反,value是一个具体的Python变量值,返回其字符串,通常用于url反向引用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# urls.py: from django.urls import register_converter, path from app01 import yearconvert,views #使用register_converter 将其注册到URL配置中: register_converter(yearconvert.FourDigitYearConverter, ‘yyyy‘ ) urlpatterns = [ path( ‘articles/<yyyy:year>/‘ , views.year_archive), ] #app01.yearconvert.py: class FourDigitYearConverter: regex = ‘[0-9]{4}‘ #规则 def to_python( self , value): return int (value) # 在这转换了类型 def to_url( self , value): return ‘%04d‘ % value #app01.views.py: from django.shortcuts import render,HttpResponse,redirect def year_archive(request,year): print (year, type (year)) return HttpResponse( ‘ok‘ ) |
视图
一个视图函数,简称视图,是一个简单的Python 函数,它接受Web请求并且返回Web响应。响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片. . . 是任何东西都可以。无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你的Python目录下面。除此之外没有更多的要求了。为了将代码放在某处,约定是将视图放置在项目或应用程序目录中的名为views.py的文件中。
一、HttpRequest对象
django将请求报文中的请求行、首部信息、内容主体封装成 HttpRequest 类中的属性。
1.request属性
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
118
119
|
""" 1.HttpRequest.GET 一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。 2.HttpRequest.POST 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。 POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。 因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST" 另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。 注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用: request.POST.getlist("hobby") 3.HttpRequest.body 一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。 但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。 4.HttpRequest.path 一个字符串,表示请求的路径组件(不含域名)。 例如:"/music/bands/the_beatles/" 5.HttpRequest.method 一个字符串,表示请求使用的HTTP 方法。必须使用大写。 例如:"GET"、"POST" 6.HttpRequest.encoding 一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 ‘utf-8‘)。 这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。 接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。 如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。 7.HttpRequest.META 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例: CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。 CONTENT_TYPE —— 请求的正文的MIME 类型。 HTTP_ACCEPT —— 响应可接收的Content-Type。 HTTP_ACCEPT_ENCODING —— 响应可接收的编码。 HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。 HTTP_HOST —— 客服端发送的HTTP Host 头部。 HTTP_REFERER —— Referring 页面。 HTTP_USER_AGENT —— 客户端的user-agent 字符串。 QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。 REMOTE_ADDR —— 客户端的IP 地址。 REMOTE_HOST —— 客户端的主机名。 REMOTE_USER —— 服务器认证后的用户。 REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。 SERVER_NAME —— 服务器的主机名。 SERVER_PORT —— 服务器的端口(是一个字符串)。 从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时, 都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。 所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。 8.HttpRequest.FILES 一个类似于字典的对象,包含所有的上传文件信息。 FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。 注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会 包含数据。否则,FILES 将为一个空的类似于字典的对象。 9.HttpRequest.COOKIES 一个标准的Python 字典,包含所有的cookie。键和值都为字符串。 10.HttpRequest.session 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。 完整的细节参见会话的文档。 11.HttpRequest.user(用户认证组件下使用) 一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。 如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。 例如: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users. user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。 ------------------------------------------------------------------------------------- 匿名用户 class models.AnonymousUser django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点: id 永远为None。 username 永远为空字符串。 get_username() 永远返回空字符串。 is_staff 和 is_superuser 永远为False。 is_active 永远为 False。 groups 和 user_permissions 永远为空。 is_anonymous() 返回True 而不是False。 is_authenticated() 返回False 而不是True。 set_password()、check_password()、save() 和delete() 引发 NotImplementedError。 New in Django 1.8: 新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。 """ |
2.request常用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
""" 1.HttpRequest.get_full_path() 返回 path,如果可以将加上查询字符串。 例如:"/music/bands/the_beatles/?print=true" 2.HttpRequest.is_ajax() 如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串‘XMLHttpRequest‘。 大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。 如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware, 你应该使用 vary_on_headers(‘HTTP_X_REQUESTED_WITH‘) 装饰你的视图以让响应能够正确地缓存。 """ |
二、HttpResponse对象
响应对象主要有三种形式:
- HttpResponse():HttpResponse()括号内直接跟一个具体的字符串作为响应体,比较直接很简单,所以这里主要介绍后面两种形式。
- render():render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。
- redirect():重定向一个URL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
""" render(request, template_name[, context]) 结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。 参数: request: 用于生成响应的请求对象。 template_name:要使用的模板的完整名称,可选的参数 context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。 render方法就是将一个模板页面中的模板语法进行渲染,最终渲染成一个html页面作为响应体。 """ return render(request, "index.html" ,{ "timer" :ctime}) # index.html 模板文件 # return render(request, "index.html", locals()) # # HttpResponse return HttpResponse(reverse( "app01:index" )) return HttpResponse( "<h1>OK</h1>" ) #redirect return redirect( "/index/" ) return redirect( ‘http://baidu.com/‘ ) |
模板
一、模板语法之变量
在 Django 模板中遍历复杂数据结构的关键是句点字符, 语法: {{var_name}}
1
2
3
4
5
6
|
<h4>{{s}}< / h4> <h4>列表:{{ l. 0 }}< / h4> <h4>列表:{{ l. 2 }}< / h4> <h4>字典:{{ dic.name }}< / h4> <h4>日期:{{ date.year }}< / h4> <h4>类对象列表:{{ person_list. 0.name }}< / h4> |
二、模板之过滤器
语法:{{obj|filter__name:param}}
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
|
""" default:如果一个变量是false或者为空,使用给定的默认值。否则,使用变量的值。例如: {{ value|default:"nothing" }} length:返回值的长度。它对字符串和列表都起作用。例如: {{ value|length }} 如果 value 是 [‘a‘, ‘b‘, ‘c‘, ‘d‘],那么输出是 4。 filesizeformat:将值格式化为一个 “人类可读的” 文件尺寸 (例如 ‘13 KB‘, ‘4.1 MB‘, ‘102 bytes‘, 等等)。例如: {{ value|filesizeformat }} 如果 value 是 123456789,输出将会是 117.7 MB。 date:如果 value=datetime.datetime.now() {{ value|date:"Y-m-d" }} slice:如果 value="hello world" {{ value|slice:"2:-1" }} truncatechars: 如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。 参数:要截断的字符数 {{ value|truncatechars:9 }} safe:Django的模板中会对HTML标签和JS等语法标签进行自动转义,这样是为了安全。如果不希望HTML元素被转义,可以这样: value="<a href="">点击</a>" {{ value|safe}} """ |
这里简单介绍一些常用的模板的过滤器,更多详见
三、模板之标签
标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})。
1、for标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
""" 遍历每一个元素: {% for person in person_list %} <p>{{ person.name }}</p> {% endfor %} 可以利用{% for obj in list reversed %}反向完成循环。 遍历一个字典: {% for key,val in dic.items %} <p>{{ forloop.counter }} {{ key }}:{{ val }}</p> {% endfor %} 注:循环序号可以通过{{ 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 """ |
2、for ... empty
1
2
3
4
5
6
|
<! - - for 标签带有一个可选的{ % empty % } 从句,以便在给出的组是空的或者没有被找到时,可以有所操作。 - - > { % for person in person_list % } <p>{{ forloop.counter0 }} {{ person.name }} , {{ person.age }}< / p> { % empty % } <p>列表为空< / p> { % endfor % } |
3、if 标签
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<! - - 注意: filter 可以用在 if 等语句后,simple_tag不可以 - - > { % if i|multi_fliter: 10 > 100 % } <p> 100 < / p> { % else % } <p>{{ i }}< / p> { % endif % } <! - - 多分支 - - > { % if num > 100 or num < 0 % } <p>无效< / p> { % elif num > 80 and num < 100 % } <p>优秀< / p> { % else % } <p>凑活吧< / p> { % endif % } |
4、with
1
2
3
4
5
|
<! - - 使用一个简单地名字缓存一个复杂的变量 - - > { % with person_list. 1.name as n % } {{ n }} {{ n }} { % endwith % } |
5、csrf_token
1
2
3
4
5
|
<form action = " " method=" post"> { % csrf_token % } <! - - 这个标签用于跨站请求伪造保护 - - > < input type = "text" name = "user" > < input type = "submit" > < / form> |
四、自定义标签和过滤器
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
|
""" 1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag. 2、在app中创建templatetags包(包名只能是templatetags) 3、创建任意 .py 文件,如:my_tags.py 4、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py 5、使用simple_tag和filter(如何调用) 注意:filter可以用在if等语句后,simple_tag不可以 """ #settings.py INSTALLED_APPS = [ ‘django.contrib.admin‘ , ‘django.contrib.auth‘ , ‘django.contrib.contenttypes‘ , ‘django.contrib.sessions‘ , ‘django.contrib.messages‘ , ‘django.contrib.staticfiles‘ , "app01" , #配置当前app ] # app01.templatetags.my_tags.py from django import template from django.utils.safestring import mark_safe register = template.Library() # register的名字是固定的,不可改变 @register . filter #自定义过滤器最多2个参数 def multi_fliter(v1, v2): return v1 * v2 @register .simple_tag #自定义标签,没有参数个数限制 def multi_tag(v1, v2, v3): return v1 * v2 * v3 @register .simple_tag def my_input( id , arg): result = "<input type=‘text‘ id=‘%s‘ class=‘%s‘ />" % ( id , arg,) return mark_safe(result) #模板中: """ {% load my_tags %} <!--注意:这块更改过要重启项目--> # num = 8 <p>{{ num|multi_fliter:20 }}</p> <p>{% multi_tag 7 9 6 %}</p> <!--注意:filter可以用在if等语句后,simple_tag不可以--> {% if num|multi_fliter:10 > 100 %} <p>100</p> {% else %} <p>{{ num }}</p> {% endif %} """ |
五、模板继承 (extend)
- 不能在一个模版中定义多个相同名字的 block 标签。
- 为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:{% block content %}...{% endblock content %}
- 子模版不必定义全部父模版中的blocks
- {% extends ‘base.html‘ %}
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
|
<! - - 模版 base.html - - > <!DOCTYPE html> <html lang = "en" > <head> <meta charset = "UTF-8" > { % block title % } <title>base< / title> { % endblock % } { % block css % } { % endblock % } < / head> <body> <div class = "header" >< / div> <div class = "container" > <div class = "row" > <div class = "col-md-3" > { % include ‘left1.html‘ % } <! - - 引入某个区域 - - > { % include ‘left2.html‘ % } <! - - 引入某个区域 - - > < / div> <div class = "col-md-9" > { % block con % } <h4>content< / h4> { % endblock content % } <! - - 更好的可读性 - - > < / div> < / div> < / div> { % block js % }{ % endblock % } < / body> < / html> |
2、继承模板
1
2
3
4
5
6
7
8
9
10
11
12
|
{ % extends ‘base.html‘ % } <! - - 它必须是模版中的第一个标签。 - - > { % block title % } <title>orders< / title> { % endblock % } { % block con % } {{ block. super }} <! - - 获取模板中con的内容 - - > <h4>订单< / h4> { % endblock con % } <! - - order.html - - > |