django 模版渲染
[toc]
4.模版渲染
4.1 settings文件配置
settings配置文件中的TEMPLATES项是对静态页面的设置,DIRS处需要写上对应的静态文件存放的位置,默认为templates
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(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',
],
},
},
]
4.2 模版语法
在html文件标签中写
{{ 变量 }} {% 逻辑 %}
4.3 万能的点 .
html文件
以下代码中dic.name就是.
的运用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ num }}</h1>
<h1>{{ str }}</h1>
<h1>{{ lst }}</h1>
<h1>{{ dic.name }}</h1>
{# #注意,调用方法时,不能加括号,所有如果方法带参数,就没法用了#}
<h1>{{ woman.play }}</h1>
<h1>{{ woman.xx }}</h1>
</body>
</html>
views文件
from django.shortcuts import render,HttpResponse,redirect
from django.views import View #CBV进程的类
# Create your views here.
def home(request):
# return HttpResponse('登陆成功')
# return render(request,'index.html')
num = 10
str = 'I am a running 的草泥马'
lst = [1,2,3,4,5,6]
dic = {'name':'小明','age':20}
class A:
money = 100
def __init__(self):
self.xx = 'oo'
def play(self):
return '什么价位?'
woman = A()
return render(request,'模版渲染.html',{'num':num,'str':str,'lst':lst,'dic':dic,'woman':woman})
运行后的初次效果
4.4 过滤器
4.4.1 过滤器用法
有参数的过滤器用法
{{ 变量|过滤器名称:'参数' }}
没参数的过滤器用法
{{ 变量|过滤器名称 }}
4.4.2 内置过滤器
views文件
from django.shortcuts import render,HttpResponse,redirect
from django.views import View #CBV进程的类
# Create your views here.
def home(request):
# return HttpResponse('登陆成功')
# return render(request,'index.html')
num = 10
str = 'I am a running 的草泥马'
lst = [1,2,3,4,5,6]
dic = {'name':'小明','age':20}
class A:
money = 100
def __init__(self):
self.xx = 'oo'
def play(self):
return '什么价位?'
woman = A()
return render(request,'模版渲染.html',{'num':num,'str':str,'lst':lst,'dic':dic,'woman':woman})
4.4.2.1 truncatechars 截断字符串
truncatechars:数字 数字表示要截断的字符数
未截断前
截断后
truncatechars:5表示截取5个字符,其中包括3个.
<h1>{{ str | truncatechars:5 }}</h1>
4.4.2.2 default 如果一个变量是false或者为空,使用给定的默认值。 否则,使用变量的值
在views文件中只有num变量,没有num1变量,因此使用default指定的值
<h1>{{ num1 | default:'没有num1这个变量' }}</h1>
4.4.2.3 length 获取变量数据长度
<h1>{{ lst | length }}</h1>
4.4.2.4 filesizeformat 大小按照人类可读方式显示
views文件中定义file_size = 1024,注意还需要在render方法中以字典的形式定义返回
<h1>{{ file_size | filesizeformat }}</h1>
4.4.2.5 slice 切片(顾头不顾腚)
<h1>{{ str | slice:'2:9' }}</h1>
使用切片截取
4.4.2.6 date 日期格式化显示
views文件
import datetime
now = datetime.datetime.now()
注意在render方法中返回
html文件
<h1>{{ now | date:'Y-m-d H:i:s' }}</h1>
4.4.2.7 safe 关闭HTML的自动转义
safe是防止xss攻击让一些js、html等等代码变成普通字符而不执行,但有的时候我们想要执行这些代码,就需要用到safe
Django的模板中在进行模板渲染的时候会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全,django担心这是用户添加的数据,比如如果有人给你评论的时候写了一段js代码,这个评论一提交,js代码就执行啦,这样就可以搞一些坏事儿了,写个弹窗的死循环,浏览器会一直弹窗,这叫做xss攻击,所以浏览器不让你这么搞,给你转义了。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过 过滤器"|safe" 的方式告诉Django这段代码是安全的不必转义。
views文件中定义了一个a_tag,我门现在就想让这个标签成为一个超链接
a_tag = "<a href='http://www.baidu.com'>百度</a>"
html文件
<h1>{{ a_tag | safe }}</h1>
没有加safe
加上safe后
4.4.2.8 join 字符串拼接列表
views文件
lst = [1,2,3,4,5,6]
html文件
<h1>{{ lst | join:"+"}}</h1>
4.4.2.9 cut 移除变量中所有的与给出的变量相同的字符串
views文件
str = 'I am a running 的草泥马'
html文件
<h1>{{ str | cut:' ' }}</h1>
4.5 标签
4.5.1 for标签
for标签语法
{% for foo in 循环的对象 %}
{% endfor %}
for标签循环列表简单示例
views文件
def home(request):
lst = [1,2,3,4,5]
return render(request,'home.html',{'lst':lst})
html文件
<body>
<ul>
{% for foo in lst %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
</body>
结果如下
<body>
<ul>
{% for foo in lst reversed %}
<li>{{ foo }}</li>
{% endfor %}
</ul>
</body>
for标签循环字典简单示例
views文件
def home(request):
lst = [1,2,3,4,5]
dic = {'name':'小明','age':20,'hobby':'唱、跳、rap、篮球'}
return render(request,'home.html',{'lst':lst,'dic':dic})
html文件
<ol>
{% for foo in dic.items %} //这里可以循环字典的键、值、键和值
<li>{{ foo }}</li>
{% endfor %}
</ol>
<ol>
{% for key,value in dic.items %}
<li>{{ key }}--->{{ value }}</li>
{% endfor %}
</ol>
for标签中的empty
{% for i in lst1 %} #当没有数据时,会生成empty的内容
<li>{{ i }}</li>
{% empty %}
<p>啥数据也没有!</p>
{% endfor %}
for标签中的forloop方法,必须在循环内使用
forloop.counter #当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
forloop.counter0 #当前循环的索引值(从0开始)
forloop.revcounter #当前循环的倒序索引值(从1开始)
forloop.revcounter0 #当前循环的倒序索引值(从0开始)
forloop.first #当前循环是不是第一次循环(布尔值)
forloop.last #当前循环是不是最后一次循环(布尔值)
forloop.parentloop #本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
forloop.counter #当前循环的索引值(从1开始),forloop是循环器,通过点来使用功能
<ol>
{% for key,value in dic.items %}
<li>{{ forloop.counter }}{{ key }}--->{{ value }}</li>
{% endfor %}
</ol>
forloop.counter0 #当前循环的索引值(从0开始)
<ol>
{% for key,value in dic.items %}
<li>{{ forloop.counter0 }}{{ key }}--->{{ value }}</li>
{% endfor %}
</ol>
forloop.first #当前循环是不是第一次循环(布尔值)
<ol>
{% for key,value in dic.items %}
<li>{{ forloop.first }} {{ key }}--->{{ value }}</li>
{% endfor %}
</ol>
forloop.parentloop #本层循环的外层循环的对象,再通过上面的几个属性来显示外层循环的计数等
views文件
def home(request):
lst = [1,2,3,4,5]
dic = {'name':'小明','age':20,'hobby':['唱','跳','rap','篮球']}
return render(request,'home.html',{'lst':lst,'dic':dic})
html文件
<ol>
{% for key,value in dic.items %}
<li>{{ forloop.last }} {{ key }}--->{{ value }}</li>
{% for foo in dic.hobby %}
{{ forloop.parentloop.counter }}---{{ forloop.counter }}<a href="">{{ foo }}</a>
{% endfor %}
{% endfor %}
</ol>
4.5.2 if标签
if语句支持
and
、or
、==
、>
、<
、!=
、<=
、>=
、in
、not in
、is
、is not
判断,注意条件两边都有空格
views文件
def home(request):
num = 100
str = 'helow'
lst = [1,2,3,4,5]
dic = {'name':'小明','age':20,'hobby':'唱、跳、rap、篮球'}
return render(request,'home.html',{'lst':lst,'dic':dic,'num':num,'str':str})
html文件
普通判断
{% if num == 100 %}
<p>数字等于100</p>
{% else %}
<p>数字不等于100</p>
{% endif %}
#语法
{% if %}
{% elif %}
{% else %}
{% endif %} //以endif结尾
结合过滤器使用
{% if str|length == 5 %}
<p>字符串长度为5</p>
{% endif %}
4.5.3 with标签
用于给比较长的数据调用起别名,只能在with标签中只用
views文件
def home(request):
lst = [1,2,{'name':'小明','age':20},4,5]
return render(request,'home.html',{'lst':lst}
html文件
html文件中想渲染views文件中返回的列表中的元素中的字典的值,如果每一次都写的话会比较长,例如lst.2.name,这个时候我们就可以取一个别名,用于给这个数据的调用,这样的话下次别的地方有引用的时候写起啦会比较简单
//例如,h1标签和a标签中都想引用这个数据的调用,没有起别名之前的写法,这样每次引用都需要在写一遍,比较麻烦
<h1>
{{ lst.2.name }}
</h1>
<a href="">{{ lst.2.name }}</a>
//这个时候就可以用到with别名的方法
<h1>
{% with lst.2.name as l %}
<a href="">{{ l }}</a>
{% endwith %}
</h1>
4.5.4 csrf_token 通过csrf认证机制
#写法
{% csrf_token %}
csrf_token
我们以post方式提交表单的时候,会报错,我们在settings里面的中间件配置里面把一个csrf的防御机制给注销了,本身不应该注销的,而是应该学会怎么使用它,并且不让自己的操作被forbiden,通过这个东西就能搞定。
这个标签用于跨站请求伪造保护,
在页面的form表单里面(注意是在form表单里面)任何位置写上{% csrf_token %},这个东西模板渲染的时候替换成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隐藏的,这个标签的值是个随机字符串,提交的时候,这个东西也被提交了,首先这个东西是我们后端渲染的时候给页面加上的,那么当你通过我给你的form表单提交数据的时候,你带着这个内容我就认识你,不带着,我就禁止你,因为后台我们django也存着这个东西,和你这个值相同的一个值,可以做对应验证是不是我给你的token,就像一个我们后台给这个用户的一个通行证,如果你用户没有按照我给你的这个正常的页面来post提交表单数据,或者说你没有先去请求我这个登陆页面,而是直接模拟请求来提交数据,那么我就能知道,你这个请求是非法的,反爬虫或者恶意攻击我的网站
4.6 自定义标签和自定义过滤器
4.6.1 自定义标签
1.在应用程序目录中创建一个templatetags目录(名称只能叫templatetags)
2.在templatetabs目录中创建xx.py
3.在xx.py中导入template
from django import template
#变量名称必须叫register
register = template.Library()
#自定义标签
@register.simple_tag
def tag(v1):
return v1 + 'tag'
使用自定义标签
urls文件
url(r'^tags/', views.tags),
views文件
def tags(request):
name = 'hehe'
return render(request,'tags.html',{'name':name})
tags.html文件
//这里表示引入应用程序目录下templatetags目录中自定义的xx.py,这个xx.py中是我们自定义的标签
{% load xx %}
<h1>
{% tag name %}
</h1>
args.html文件中不给自定义标签传参数
views文件中指定给自定义的标签传2个参数,v1是views中tag函数定义的变量name,v2就是args.html中自定义标签传的一个参数
from django import template
#变量名称必须叫register
register = template.Library()
#自定义标签
@register.simple_tag
def tag(v1,v2):
return v1 + 'tag' + v2
args.html文件中给自定义标签传参
<h1>
{% tag name '参数1' %}
</h1>
4.6.2 自定义过滤器
1.在应用程序目录中创建一个templatetags目录(名称只能叫templatetags)
2.在templatetabs目录中创建xx.py
3.在xx.py中导入template
from django import template
#变量名称必须叫register
register = template.Library()
#自定义过滤器,最多2个参数 这里自定义一个过滤器,接受任意一个参数,给这个参数后边加一个字符串
@register.filter
def oo(v1):
return v1 + 'oo'
使用自定义过滤器
urls文件
url(r'^tags/', views.tags),
views文件
def tags(request):
name = 'hehe'
return render(request,'tags.html',{'name':name})
tags.html
//这里表示引入应用程序目录下templatetags目录中自定义的xx.py,这个xx.py中是我们自定义的过滤器
{% load xx %}
<h1>
{{ name | oo }}
</h1>
结果如下,可以看到,我们自定义的过滤器,接受任意一个参数,给这个参数后边加一个字符串oo
上述结果是xx.py就是我们自定义的过滤器文件中的函数只传了一个参数,现在我们给这个函数传2个参数(最多传两个参数)
xx.py写法
from django import template
#变量名称必须叫register
register = template.Library()
#自定义过滤器,最多2个参数 这里自定义一个过滤器,接受任意一个参数,给这个参数后边加一个字符串
@register.filter
def oo(v1,v2):
return v2 + 'oo' + v1
上述代码中v1是views中定义的name变量的值,也就是hehe,v2就是tags.html中函数oo后面传的参数,因此打印的结果就是
哈哈oohehe
urls文件
url(r'^tags/', views.tags),
views文件
def tags(request):
name = 'hehe'
return render(request,'tags.html',{'name':name})
tags.html
//这里表示引入应用程序目录下templatetags目录中自定义的xx.py,这个xx.py中是我们自定义的过滤器
{% load xx %}
<h1>
{{ name | oo:'哈哈' }}
</h1>
4.6.3 inclusion_tag 修改引入组件的样式(非常难理解)
inclusion_tag作用如下
接下来开始整个过程
第一步、先在django项目同路径下的templates目录下创建一个菜单静态页面作为一个组件
zujian.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.menus{
width: 200px;
}
.menus .item{
background-color: green;
color: white;
height: 50px;
}
</style>
</head>
<body>
<div class="menus">
<div class="item">菜单1</div>
<div class="item">菜单2</div>
<div class="item">菜单3</div>
</div>
</body>
</html>
效果如下
第二步、分别在urls和views文件中写上对应的访问路径和函数
这里在后边定义一个xx.html,这个xx.html引入组件文件zujian.html,并且访问路径是xx,视图中的函数也叫xx(返回xx.html)
urls文件
url(r'^xx/', views.xx),
views文件
def xx(request):
return render(request,'xx.html')
第三步、还是在templates目录下创建一个xx.html文件,这个html文件引入刚才创建的组件文件
xx.html文件初始内容如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.nav{
height: 200px;
width: 150px;
background-color: burlywood;
}
</style>
</head>
<body>
<div class="nav">我是xx.html,一会我要引入组件中的样式,就是组件中的那个菜单栏,并且我不修改引入的样式,只是修改菜单栏为其他内容</div>
</body>
</html>
初始xx.html
接下来在xx.html文件中引入组件文件的样式
在div标签下引入zujian.html
<div class="nav">我是xx.html,一会我要引入组件中的样式,就是组件中的那个菜单栏,并且我不修改引入的样式,只是修改菜单栏为其他内容</div>
{% include 'zujian.html' %}
引入组件后的样式,绿色为zujian.html文件中的内容
接下来想要将引入的样式中的菜单栏变为其他内容,需要做以下操作,在组件文件zujian.html文件中将想要更改的内容利用for循环便利
zujian.html文件
<div class="menus">
//利用for循环遍历data变量,foo就是data变量中的所有内容,这样的话就做成了动态的效果,原先的菜单栏div标签现在只需要写一个,因为foo是变量data中所有的值
{% for foo in data %}
<div class="item">{{ foo }}</div>
{% endfor %}
//注释之前的菜单栏,因为我们需要用到动态传入内容
{# <div class="item">菜单1</div>#}
{# <div class="item">菜单2</div>#}
{# <div class="item">菜单3</div>#}
</div>
这里有个问题,现在想把zujian.html文件中的菜单栏做一下动态修改,这里写了从data中取值,但是循环遍历的data是从哪来的???这时就引出了inclusion_tag
inclusion_tag需要写在templatetags目录下自定义的py文件中,而data就是我们自定义的返回给xx.html文件的动态内容,因为xx.html引入zujian.html的样式是固定的,只有zujian.html文件中定义的内容
第四步、在templatetags目录下创建一个mytags.py
templatetags目录是在django项目的应用程序目录下创建的目录,在自定义标签和自定义过滤器的时候必须创建这个目录,且名字只能是这个,在这个templatetags目录下创建的py文件中自定义标签和过滤器
mytags.py
@register.inclusion_tag('zujian.html')是固定写法,括号中的参数就是组件文件,这里的data是我们自定义的字典
@register.inclusion_tag('zujian.html')
def hehe(v1):
return {'data':['唱','跳','rap','篮球']}
第五步、在xx.html文件中引入动态内容
<div class="nav">我是xx.html,一会我要引入组件中的样式,就是组件中的那个菜单栏,并且我不修改引入的样式,只是修改菜单栏为其他内容</div>
{#{% include 'zujian.html' %}#}
{% load mytags %} //引入自定义函数的那个文件名
{% hehe %} //引入自定义函数,用于返回data
最终运行效果如下,引入的组件的背景颜色绿色没有改变,但是改变了之前的菜单栏
整个过程总结
1.定义urls
url(r'^xx/', views.xx),
2.定义视图
def xx(request):
return render(request,'xx.html')
3.xx.html文件引入组件文件zujian.html,组件中只定义了一个背景色,但是xx.html文件想要动态的添加一些内容,例如菜单栏,此时需要在组件文件中做如下改动
组件文件中定义的背景色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.menus{
width: 200px;
}
</style>
</head>
<body>
<div class="menus">
</div>
</body>
</html>
利用for循环去循环一个变量,例如data,这个变量是在django项目下的应用程序目录下的templatetags下的任意名称py文件中利用@register.inclusion_tag('zujian.html')
和自定义函数中的return返回值定义的变量
应用程序下templates目录中定义一个mytags.py(名称任意),文件内容如下
inclusion_tag中必须跟一个参数,这个参数必须是组件文件,自定义一个函数hehe(名称任意),return的返回值会返回给组件文件
mytags.py文件内容如下
from django import template
register = template.Library()
@register.inclusion_tag('zujian.html')
def hehe():
return {'data':['唱','跳','rap','篮球']}
4.第3步中的data变量已经返回给了组件文件,因此xx.html文件中需要引入应用程序下的templatetags中定义的那个py文件(这里是mytag.py)
还需要引入这个py文件中自定义的函数的名称(这里是hehe)
mytags.py(自定义标签需要在应用程序下的templatetags目录中定义一个任意的py文件,然后在这个文件中写自定义标签内容)
xx.html文件内容如下
<div class="nav">我是xx.html,一会我要引入组件中的样式,就是组件中的那个菜单栏,并且我不修改引入的样式,只是修改菜单栏为其他内容</div>
{#{% include 'zujian.html' %}#}
{% load mytags %}
{% hehe %}
#参数说明
{% load mytags %} //引入应用程序下的templatetags中定义的那个py文件(这里是mytags.py)
{% hehe %} //引入这个py文件(mytags.py)中自定义的函数的名称(这里是hehe)
最终的渲染效果就由应用程序下的templatetags中定义的那个py文件(这里是mytags.py)中定义的函数中自定义的返回值决定
这里定义的data是一个字典,data会返回给组件文件用于动态渲染
from django import template
register = template.Library()
@register.inclusion_tag('zujian.html')
def hehe():
return {'data':['唱','跳','rap','篮球']}
关于动态返回内容的一个问题
写在mytags中是写死的,我们应该写成动态的,所以应该写在views中从数据库中获取数据达到动态返回的效果,因此修改mytags文件如下
mytags文件
from django import template
register = template.Library()
@register.inclusion_tag('zujian.html')
#这里的v1就是给xx.html文件中引入hehe函数能够传一个参数
def hehe(v1):
return {'data':v1}
views文件
def xx(request):
#这里的lst就相当于从数据库中动态获取的数据
lst = ['唱1','跳1','rap1','篮球1']
return render(request,'xx.html',{'lst':lst})
xx.html文件
<div class="nav">我是xx.html,一会我要引入组件中的样式,就是组件中的那个菜单栏,并且我不修改引入的样式,只是修改菜单栏为其他内容</div>
{#{% include 'zujian.html' %}#}
{% load mytags %}
{% hehe lst %} //在这里引入views中定义的lst
最终真正的动态获取内容效果如下
4.7 组件
组件类似于python中的模块,组件是把其他html页面引入过来,但是不能修改引入的文件的内容
组件文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
</body>
</html>
自定义文件
在自定义文件中,我们想引入组件文件中的列表样式,需要如下代码,这个就是在自定义文件中表示引入组件.html文件
#写法
{% include '组件.html' %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.c1{
background-color: green;
}
</style>
</head>
<body>
{% include '组件.html' %}
<div class="c1">我是一个引入了组件文件的自定义文件</div>
</body>
</html>
4.8 模版继承
我们在写多个静态页面的时候可能会有一些相同的样式,这样的话每写一个页面就需要复制相同的代码,这样就造成了代码大量重复,此时就用到了模版继承,我们可以把相同样式的页面的代码单独放在一个模版文件中,其余页面继承这个模版文件,然后在设置自定义内容即可,这样就不用重复写相同样式的代码了
模版文件 base.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.nav{
background-color: pink;
height: 40px;
}
.left-menu{
display: inline-block;
width: 200px;
background-color: mediumpurple;
}
.content{
display: inline-block;
height: 200px;
width: 600px;
background-color: burlywood;
color:white;
}
ul{
padding: 0;
margin: 0;
}
</style>
#这里表示预留css样式,子模版继承后可以修改模版的样式
{% block css %}
{% endblock %}
</head>
<body>
<div class="nav">
<a href="">个人中心</a>
<a href="">登录|注册</a>
</div>
<div class="left-menu">
<ul>
<li>
<a href="/menu01/">菜单1</a>
</li>
<li>
<a href="/menu02/">菜单2</a>
</li>
<li>
<a href="">菜单3</a>
</li>
</ul>
</div>
<div class="content">
{% block content %}
base页面
<a href="">xxx</a>
{% endblock %}
</div>
</body>
{% block js %}
{% endblock %}
</html>
模版继承的写法
在模版html文件中需要用到block方法,例如上述示例中,我们想要菜单1和菜单2有自己的自定义界面而不继承模版文件,写法如下
<div class="content">
{% block content %}
base页面
<a href="">xxx</a>
{% endblock %}
</div>
<div class="content">这个标签就是菜单1和菜单2中需要单独设置样式的标签,为了不继承模版文件,需要在这个标签写如下内容
block中包含的a标签就是菜单1和菜单2的html文件中需要重写的
{% block content %}
base页面
<a href="">xxx</a>
{% endblock %}
这段代码的意思是,模版文件中的base页面不希望被继承,这里就单独把这个页面预留出来,接下来在菜单1和菜单2的html文件中在单独写这块的样式,写法如下
//这里表示继承模版文件base.html
{% extends 'base.html' %}
因为不需要继承模版文件中的 base页面 处的内容,而模版文件中也把这一块内容已经预留出来了,并且定义了预留名称为 content,在菜单1和菜单2的html文件中之需要引入这个模版预留名称,这样就可以自定义自己的样式了,写法如下
{% block content %}
菜单1的内容
{% endblock %}
base.html文件如上,现在我们设置菜单1、菜单2的自定义内容,需要做以下操作
urls文件
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
#这个就是模版页面
url(r'^base/', views.base),
#下边两个是菜单1和菜单2返回的页面
url(r'^menu01/', views.menu01),
url(r'^menu02/', views.menu02),
]
views文件
def base(request):
return render(request,'base.html')
def menu01(request):
return render(request,'menu01.html')
def menu02(request):
return render(request,'menu02.html')
menu01.html
{% extends 'base.html' %}
<style>
.content{
display: inline-block;
height: 200px;
width: 600px;
background-color: green;
color:white;
}
</style>
{% endblock %}
{% block content %}
菜单1的内容
{% endblock %}
menu02.html
{% extends 'base.html' %}
{% block content %}
菜单2的内容
{% endblock %}
访问base页面,点击菜单1,返回页面如下,因为在menu01.html文件中,我门自己指定了样式,因此背景颜色就和模版的不同了
访问base页面,点击菜单2,返回页面如下
block.super()
这个方法就是继承模板预留块的内容的同时在自定义内容
{% block content %}
{{ block.super }} #将模版中的content这个名称的块中的内容拿过来
菜单1的内容
{% endblock %}
4.9 url别名和反向解析
url别名的作用是当修改了url的访问路径,视图逻辑中返回的url路径也需要改动,其他相关联的地方也可能需要改动,这个时候我们在url中定义一个别名,如果后续更改了url的访问路径,其他地方只需要用到url别名的反向解析就能自动找到别名对应的url路径,这样的话只需要修改url路径而不更改其余地方
写法:
url(r'^login/v2/', views.login,name='login'),
视图中反向解析:
from django.urls import reverse
def login(request):
print(reverse('login')) #/login/v2/
if request.method == 'GET':
return render(request,'login.html')
else:
uname = request.POST.get('uname')
pwd = request.POST.get('pwd')
if uname == 'admin' and pwd == 'admin':
return HttpResponse('ok')
else:
return redirect(reverse('login')) #使用反向解析
html模板渲染时反向解析的语法{% url 别名 %}
<form action="{% url 'login' %}" method="post">
{% csrf_token %}
用户名:<input type="text" name="uname">
密码:<input type="text" name="pwd">
<input type="submit">
</form>
进行html模板渲染时反向解析时,如果定义了命名空间,则在html中需要如下写法
html模板渲染时反向解析的语法{% url 命名空间:别名 %}
4.10 include路由分发和url命名空间
4.10.1 include路由分发
include路由分发就是将不同的url放在不同的应用程序下的urls文件中,先匹配一个应用程序的路径,然后在分别去这两个应用程序对应的urls文件中找下一级目录
例如,现在有app01和app02两个应用程序,现在设置的访问路径如下
/app01/index
/app02/index
访问到app01就去app01路径下找index