在刚刚介绍完的视图层中咱们提到,浏览器发送的请求信息会转发给视图函数进行处理,而视图函数在通过一系列处理后必需要有返回信息给浏览器。若是咱们要返回html
标签、css
等数据给浏览器进行渲染,咱们能够在视图函数中这么作css
def current_datetime(request): now = datetime.datetime.now() html = "<html><body>It is now %s.</body></html>" % now return HttpResponse(html)
上例所示,咱们直接将HTML
代码放到视图函数里,而后进行返回,这可使咱们很直观地看清楚浏览器从发送请求到看到前端界面内容的这个过程当中视图函数的基本工做原理,可是这种将前端代码与后端代码耦合到了一块儿开发方式,会存在如下问题html
基于上述缘由,将前端页面和Python
的代码分离是一种不错的开发模式。 为此 Django
专门提供了模板系统 (Template System
,即模板层)来实现这种模式,这就是本章要具体讨论的问题。前端
存放于templates
目录下的html
文件称之为模板文件,若是咱们想要返回的html
页面中的数据是动态的,那么必须在html
页面中嵌入变量,Django的模板 = HTML
+ 模板语法,这便用到了django
的模板语法,具体来讲,django
的模板语法有如下重点python
1、变量:{{ 变量名 }} 1.1 深度查询:句点符的应用 1.2 过滤器 2、标签:{% 标签名 %} 3、自定义标签和过滤器 4、模板的导入和继承
下面就让咱们来一一介绍它们 ~ ~ ~ ~jquery
若是html
代码中的数据不是固定死的,而是动态变化的,则必须在html
中嵌入变量,为此,模板语法提供了变量的概念,容许咱们在html
代码中嵌入变量,咱们只须要在视图函数中用render
的方法为html
文件中指定的变量赋值便可,具体用法以下git
test.html
程序员
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>{{ msg }}</p> <p>{{ dic }}</p> <p>{{ obj }}</p> <p>{{ li }}</p> </body> </html>
咱们须要在视图函数中为模板test.html
的变量名msg
、li
、dic
、obj
、obj_li
赋值,views.py
内容以下数据库
from django.shortcuts import render def test(request): # 传给模板的变量值能够是任意python类型,以下 msg='hello world' dic={'k1':1,'k2':2} class Person(object): def __init__(self,name,age): self.name=name self.age=age obj=Person('egon',18) li = [1,'aaa',obj] return render(request,'test.html',{'msg':msg,'dic':dic,'obj':obj,'li':li}) # 注意: # 一、render函数的第三个参数包含了要传给模板的变量值,是一个字典类型,该字典中的key必须与模板文件中的变量名相对应,render函数会去templates目录下找到模板文件,而后根据字典中的key对应到模板文件中的变量名进行赋值操做,最后将赋值后的模板文件内容返回给浏览器 # 二、能够将render函数的第三个参数简写为locals(),以下 return render(request,'test.html',locals()) #locals()会将函数test内定义的名字与值转换为字典中的k与v
当视图函数传给模板的值中包含多个元素时,若想取出其中的单个元素,就必须使用句点符了。句点符既能够引用容器类型的元素,也能够引用对象的方法,以下npm
test.html
django
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--调用字符串对象的upper方法,注意不要加括号--> <p>{{ msg.upper }}</p> <!--取字典中k1对应的值--> <p>{{ dic.k1 }}</p> <!--取对象的name属性--> <p>{{ obj.name }}</p> <!--取列表的第2个元素,而后变成大写--> <p>{{ li.1.upper }}</p> <!--取列表的第3个元素,并取该元素的age属性--> <p>{{ li.2.age }}</p> </body> </html>
过滤器相似于python
的内置函数,用来把视图传入的变量值加以修饰后再显示,具体语法以下
{{ 变量名|过滤器名:传给过滤器的参数 }}
经常使用内置过滤器
# 一、default # 做用:若是一个变量值是False或者为空,使用default后指定的默认值,不然,使用变量自己的值,若是value=" "则输出"nothing" {{ value|default:"nothing" }} # 二、length # 做用:返回值的长度。它对字符串、列表、字典等容器类型都起做用,若是value是 ['a', 'b', 'c', 'd'],那么输出是4 {{ value|length }} # 三、filesizeformat # 做用:将值的格式化为一个"人类可读的"文件尺寸(如13KB、4.1 MB、102bytes等等),若是 value 是 12312312321,输出将会是 11.5 GB {{ value|filesizeformat }} # 四、date # 做用:将日期按照指定的格式输出,若是value=datetime.datetime.now(),按照格式Y-m-d则输出2019-02-02 {{ value|date:"Y-m-d" }} # 五、slice # 做用:对输出的字符串进行切片操做,顾头不顾尾,若是value=“egon“,则输出"eg" {{ value|slice:"0:2" }} # 六、truncatechars # 做用:若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列("...")结尾,若是value="hello world egon 嘎嘎",则输出"hello...",注意8个字符也包含末尾的3个点 {{ value|truncatechars:8 }} # 七、truncatewords # 做用:同truncatechars,但truncatewords是按照单词截断,注意末尾的3个点不算做单词,若是value="hello world egon 嘎嘎",则输出"hello world ..." {{ value|truncatewords:2 }} # 八、safe # 做用:出于安全考虑,Django的模板会对HTML标签、JS等语法标签进行自动转义, 例如value="<script>alert(123)</script>", 模板变量{{ value }}会被渲染成<script>alert(123)</script> 交给浏览器后会被解析成普通字符”<script>alert(123)</script>“,失去了js代码的语法意义,但若是咱们就想让模板变量{{ value }}被渲染的结果又语法意义,那么就用到了过滤器safe, 好比value='<a href="https://www.baidu.com">点我啊</a>',在被safe过滤器处理后就成为了真正的超连接, 不加safe过滤器则会当作普通字符显示"<a href="https://www.baidu.com">点我啊</a>" {{ value|safe }}
其余过滤器(了解)
过滤器 | 描述 | 示例 |
---|---|---|
upper | 以大写方式输出 | {{ user.name | upper }} |
add | 给value加上一个数值 | {{ user.age | add:”5” }} |
addslashes | 单引号加上转义号 | |
capfirst | 第一个字母大写 | {{ ‘good’| capfirst }} 返回”Good” |
center | 输出指定长度的字符串,把变量居中 | {{ “abcd”| center:”50” }} |
cut | 删除指定字符串 | {{ “You are not a Englishman” | cut:”not” }} |
date | 格式化日期 | |
default | 若是值不存在,则使用默认值代替 | {{ value | default:”(N/A)” }} |
default_if_none | 若是值为None, 则使用默认值代替 | |
dictsort | 按某字段排序,变量必须是一个dictionary | {% for moment in moments | dictsort:”id” %} |
dictsortreversed | 按某字段倒序排序,变量必须是dictionary | |
divisibleby | 判断是否能够被数字整除 | {{ 224 | divisibleby:2 }} 返回 True |
escape | 按HTML转义,好比将”<”转换为”<” | |
filesizeformat | 增长数字的可读性,转换结果为13KB,89MB,3Bytes等 | {{ 1024 | filesizeformat }} 返回 1.0KB |
first | 返回列表的第1个元素,变量必须是一个列表 | |
floatformat | 转换为指定精度的小数,默认保留1位小数 | {{ 3.1415926 | floatformat:3 }} 返回 3.142 四舍五入 |
get_digit | 从个位数开始截取指定位置的数字 | {{ 123456 | get_digit:’1’}} |
join | 用指定分隔符链接列表 | {{ [‘abc’,’45’] | join:’’ }} 返回 abc45 |
length | 返回列表中元素的个数或字符串长度 | |
length_is | 检查列表,字符串长度是否符合指定的值 | {{ ‘hello’| length_is:’3’ }} |
linebreaks | 用或 标签包裹变量 | {{ “Hi\n\nDavid”|linebreaks }} 返回HiDavid |
linebreaksbr | 用 标签代替换行符 | |
linenumbers | 为变量中的每一行加上行号 | |
ljust | 输出指定长度的字符串,变量左对齐 | {{‘ab’|ljust:5}}返回 ‘ab ’ |
lower | 字符串变小写 | |
make_list | 将字符串转换为列表 | |
pluralize | 根据数字肯定是否输出英文复数符号 | |
random | 返回列表的随机一项 | |
removetags | 删除字符串中指定的HTML标记 | {{value | removetags: “h1 h2”}} |
rjust | 输出指定长度的字符串,变量右对齐 | |
slice | 切片操做, 返回列表 | {{[3,9,1] | slice:’:2’}} 返回 [3,9] {{ 'asdikfjhihgie' | slice:':5' }} 返回 ‘asdik’ |
slugify | 在字符串中留下减号和下划线,其它符号删除,空格用减号替换 | {{ '5-2=3and5 2=3' | slugify }} 返回 5-23and5-23 |
stringformat | 字符串格式化,语法同python | |
time | 返回日期的时间部分 | |
timesince | 以“到如今为止过了多长时间”显示时间变量 | 结果可能为 45days, 3 hours |
timeuntil | 以“从如今开始到时间变量”还有多长时间显示时间变量 | |
title | 每一个单词首字母大写 | |
truncatewords | 将字符串转换为省略表达方式 | {{ 'This is a pen' | truncatewords:2 }}返回``This is ... |
truncatewords_html | 同上,但保留其中的HTML标签 | {{ '<p>This is a pen</p>' | truncatewords:2 }}返回``<p>This is ...</p> |
urlencode | 将字符串中的特殊字符转换为url兼容表达方式 | {{ ‘http://www.aaa.com/foo?a=b&b=c’ | urlencode}} |
urlize | 将变量字符串中的url由纯文本变为连接 | |
wordcount | 返回变量字符串中的单词数 | |
yesno | 将布尔变量转换为字符串yes, no 或maybe | {{ True | yesno }}{{ False | yesno }}{{ None | yesno }} ``返回 ``yes``no ``maybe |
标签是为了在模板中完成一些特殊功能,语法为{% 标签名 %}
,一些标签还须要搭配结束标签 {% endtag %}
for
标签# 一、遍历每个元素: {% for person in person_list %} <p>{{ person.name }}</p> {% endfor %} # 二、能够利用{% for obj in list reversed %}反向循环。 # 三、遍历一个字典: {% for key,val in dic.items %} <p>{{ key }}:{{ val }}</p> {% endfor %} # 四、循环序号能够经过{{ forloop }}显示 forloop.counter 当前循环的索引值(从1开始) forloop.counter0 当前循环的索引值(从0开始) forloop.revcounter 当前循环的倒序索引值(从1开始) forloop.revcounter0 当前循环的倒序索引值(从0开始) forloop.first 当前循环是第一次循环则返回True,不然返回False forloop.last 当前循环是最后一次循环则返回True,不然返回False forloop.parentloop 本层循环的外层循环 # 五、for标签能够带有一个可选的{% empty %} 从句,在变量person_list为空或者没有被找到时,则执行empty子句 {% for person in person_list %} <p>{{ person.name }}</p> {% empty %} <p>sorry,no person here</p> {% endfor %}
url.py
from django.urls import re_path from app01 import views urlpatterns = [ re_path(r'^test/',views.test) ]
view.py
def test(request): names=['egon','kevin'] dic={'name':'egon','age':18,'sex':'male'} list1=[] return render(request,'test.html',locals())
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <hr> {% for name in names %} <p>{{ forloop.counter0 }} {{ name }}</p> {% endfor %} <!-- 输出结果为: 0 egon 1 kevin --> <hr> {% for name in names reversed %} <p>{{ forloop.revcounter0 }} {{ name }}</p> {% endfor %} <!-- 输出结果为: 1 kevin 0 egon --> <hr> {% for k,v in dic.items %} <p>{{ forloop.counter }} {{ k }} {{ v }}</p> {% endfor %} <!-- 输出结果为: 1 name egon 2 age 18 3 sex male --> <hr> {% for item in list1 %} <p>{{ item }}</p> {% empty %} <p>sorry,no value here</p> {% endfor %} <!-- 输出结果为: sorry,no value here --> </body> </html>
if
标签# 一、注意: {% if 条件 %}条件为真时if的子句才会生效,条件也能够是一个变量,if会对变量进行求值,在变量值为空、或者视图没有为其传值的状况下均为False # 二、具体语法 {% if num > 100 or num < 0 %} <p>无效</p> {% elif num > 80 and num < 100 %} <p>优秀</p> {% else %} <p>凑活吧</p> {% endif %} #三、if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
urls.py
from django.urls import path,register_converter,re_path from app01 import views urlpatterns = [ # 输入http://127.0.0.1:8008/或者http://127.0.0.1:8008/index/都会转发给视图函数index re_path(r'^$',views.index), re_path(r'^index/$',views.index), re_path(r'^login/',views.login), ]
views.py
from django.shortcuts import render def index(request): return render(request,'index.html') def login(request): if request.method == 'GET': return render(request,'login.html') name=request.POST.get('name') pwd=request.POST.get('pwd') if name == 'egon' and pwd == '123': current_user=name return render(request,'index.html',locals()) else: msg='帐号或密码错误' return render(request,'login.html',locals())
在templates
目录下新建模板文件index.html
与login.html
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> <h3>首页</h3> <!-- 若是用户已经登陆,则current_user变量有值,if判断结果为真,会打印变量current_user的值,为当前登陆的用户名 若是用户没有登陆,则current_user变量无值,if判断结果为假,会打印a标签要求用户先登陆 --> {% if current_user %} <p>当前登陆用户为:{{ current_user }}</p> {% else %} <p><a href="/login/">请先登陆</a></p> {% endif %} </body> </html>
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登陆页面</title> </head> <body> <form action="" method="POST"> {% csrf_token %} <p>用户名:<input type="text" name="name"></p> <p>密码:<input type="password" name="pwd"></p> <p><input type="submit" value="提交"></p> </form> <!--输错帐号密码时的提示信息--> <p style="color: red">{{ msg }}</p> </body> </html>
测试
python manage.py runserver 8008 #在浏览器输入http://127.0.0.1:8008/,而后点击登陆,输入帐号密码进行验证......
with
标签# with标签用来为一个复杂的变量名起别名,若是变量的值来自于数据库,在起别名后只须要使用别名便可,无需每次都向数据库发送请求来从新获取变量的值 {% with li.1.upper as v %} {{ v }} {% endwith %}
csrf_token
标签# 当用form表单提交POST请求时必须加上标签{% csrf_token%},该标签用于防止跨站伪造请求 <form action="" method="POST"> {% csrf_token %} <p>用户名:<input type="text" name="name"></p> <p>密码:<input type="password" name="pwd"></p> <p><input type="submit" value="提交"></p> </form> # 具体工做原理为: # 一、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,该标签包含了由服务端生成的一串随机字符串,如<input type="hidden" name="csrfmiddlewaretoken" value="dmje28mFo...OvnZ5"> # 二、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,对比成功则处理该POST请求,不然拒绝,以此来肯定客户端的身份
当内置的过滤器或标签没法知足咱们需求时,咱们能够自定义,具体操做步骤以下
settings
中的INSTALLED_APPS
添加当前app
的名字,否则django
没法找到自定义的过滤器或标签settings.py
# 在settings.py中找到该列表,而后加以配置 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01.apps.App01Config', 'app01', # 添加当前app的名字 ]
app01
中建立子文件夹templatetags
(文件夹名只能是templatetags
)templatetags
新建任意.py文件,如my_tags.py
,在该文件中自定义过滤器或标签,文件内容以下from django import template register = template.Library() # 注意变量名必须为register,不可改变 #一、自定义过滤器 @register.filter def my_multi_filter(v1 ,v2): # 自定义的过滤器只能定义最多两个参数,针对{{ value1 | filter_multi:value2 }},参数传递为v1=value1,v2=value2 return v1 * v2 #二、自定义标签 @register.simple_tag def my_multi_tag(v1, v2): # 自定义的标签能够定义多个参数 return v1 * v2 #三、自定义标签扩展之mark_safe # 注释:咱们能够用内置的标签safe来让标签内容有语法意义,若是咱们想让自定义标签处理的结果也有语法意义,则不能使用内置标签safe了,须要使用mark_safe,能够实现与内置标签safe一样的功能 from django.utils.safestring import mark_safe @register.simple_tag def my_input_tag(id, name): res = "<input type='text' id='%s' name='%s' />" % (id, name) return mark_safe(res)
django
方可生效<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--必须先加载存有自定义过滤器和标签的文件--> {% load my_tags %} <!--salary的值为10,通过滤器my_multi_filter的处理结果为120--> {{ salary|my_multi_filter:12 }} <!--结果为2--> {% my_multi_tag 1 2 %} <!-- 结果为一个input标签,该表的属性id="inp1" name="username" 注意:input的属性值均为字符串类型,因此my_input_tag后的两个值均为字符串类型 --> {% my_input_tag "inp1" "username" %} </body> </html>
对比自定义标签与自定义过滤器
#一、自定义过滤器只能传两个参数,而自定义标签却能够传多个参数 #二、过滤器能够用于if判断,而标签不能 {% if salary|my_multi_filter:12 > 200 %} <p>优秀</p> {% else %} <p>垃圾</p> {% endif %}
在实际开发中,模板文件彼此之间可能会有大量冗余代码,为此django
提供了专门的语法来解决这个问题,主要围绕三种标签的使用:include
标签、extends
标签、block
标签,详解以下
# 做用:在一个模板文件中,引入/重用另一个模板文件的内容, {% include '模版名称' %}
能够把广告栏写到专门的文件里advertise.html
<div class="adv"> <div class="panel panel-default"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-danger"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> <div class="panel-body"> Panel content </div> </div> <div class="panel panel-warning"> <div class="panel-heading"> <h3 class="panel-title">Panel title</h3> </div> <div class="panel-body"> Panel content </div> </div> </div>
而后在base.html
文件中用include
标签引入advertise.html
文件的内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> * { margin: 0; padding: 0; } .header { height: 50px; width: 100%; background-color: black; } </style> </head> <body> <div class="header"></div> <div class="container"> <div class="row"> <div class="col-md-3"> <!--在base.html引入advertise.html文件的内容--> {% include "advertise.html" %} </div> <div class="col-md-9"></div> </div> </div> </body> </html>
extends
标签、block
标签#做用:在一个模板文件中,引入/重用另一个模板文件的内容 {% extends "模版名称" %} # 也就是说include有的功能extends全都有,可是extends能够搭配一个block标签,用于在继承的基础上定制新的内容
Django
模版引擎中最复杂且最强大的部分就是模版继承了。咱们以先建立一个基本的“骨架”模版,它包含咱们站点中的所有元素,而且能够定义多处blocks
,例如咱们建立base.html
内容以下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> {% block title %}自定义title名{% endblock %} </title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> * { margin: 0; padding: 0; } .header { height: 50px; width: 100%; background-color: #919191; margin-bottom: 20px; } </style> </head> <body> <div class="header"></div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="list-group"> {% block sidebar %} <a href="#" class="list-group-item active">服装城</a> <a href="#" class="list-group-item">美妆馆</a> <a href="#" class="list-group-item">超市</a> <a href="#" class="list-group-item">全球购</a> <a href="#" class="list-group-item">闪购</a> <a href="#" class="list-group-item">团购</a> {% endblock %} </div> </div> <div class="col-md-9"> {% block content %} base.html页面内容 {% endblock %} </div> </div> </div> </body> </html>
模板base.html
定义了一个能够用于两列排版页面的简单HTML
骨架。咱们新建子模板index.html
的主要工做就是继承base.html
而后填充/覆盖其内部的blocks
。
{% extends "base.html" %} <!--用新内容彻底覆盖了父模板内容--> {% block title %} index页面 {% endblock %} {% block sidebar %} <!--该变量会将父模板中sidebar中原来的内容继承过来,而后咱们能够在此基础上新增,不然就是纯粹地覆盖--> {{ block.super }} <!--在继承父模板内容的基础上新增的标签--> <a href="#" class="list-group-item">拍卖</a> <a href="#" class="list-group-item">金融</a> {% endblock %} {% block content %} <!--用新内容彻底覆盖了父模板内容--> <p>index页面内容</p> {% endblock %}
咱们经过django
访问index.html
看到内容以下(block
标签的内容都完成了替换或更新)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> index页面 </title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <style> * { margin: 0; padding: 0; } .header { height: 50px; width: 100%; background-color: #919191; margin-bottom: 20px; } </style> </head> <body> <div class="header"></div> <div class="container"> <div class="row"> <div class="col-md-3"> <div class="list-group"> <!--该变量会将父模板中sidebar中原来的内容继承过来,而后咱们能够在此基础上新增,不然就是纯粹地覆盖--> <a href="#" class="list-group-item active">服装城</a> <a href="#" class="list-group-item">美妆馆</a> <a href="#" class="list-group-item">超市</a> <a href="#" class="list-group-item">全球购</a> <a href="#" class="list-group-item">闪购</a> <a href="#" class="list-group-item">团购</a> <!--在继承父模板内容的基础上新增的标签--> <a href="#" class="list-group-item">拍卖</a> <a href="#" class="list-group-item">金融</a> </div> </div> <div class="col-md-9"> <!--用新内容彻底覆盖了父模板内容--> <p>index页面内容</p> </div> </div> </div> </body> </html>
#一、标签extends必须放在首行,base.html中block越多可定制性越强 #二、include仅仅只是彻底引用其余模板文件,而extends却能够搭配block在引用的基础上进行扩写 #三、变量{{ block.super }} 能够重用父类的内容,而后在父类基础上增长新内容,而不是彻底覆盖 #四、为了提高可读性,咱们能够给标签{% endblock %} 起一个名字 。例如: {% block content %} ... {% endblock content %} #五、在一个模版中不能出现重名的block标签。
咱们在编写模板文件时,须要大量引用css
、js
、图片等静态文件,若是咱们将这些文件在服务端存放的路径都固定写死那么将很是不利于后期的扩展,咱们能够这么作
settings.py
STATIC_URL = '/static/' # 找到这一行,而后新增下述代码 STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'statics'),# 获取静态文件在服务端的绝对路径 ] #STATIC_URL = '/static/'就是为静态文件的绝对路径起了一个别名,之后咱们只须要用路径/static/便可
statics
,为了更便于管理,能够在statics
下新建子文件夹css
、js
、img
等index.html
,在该文件中对静态文件的引用以下<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/css/my.css"> </head> <body> <h4>我是红色的,点我就绿</h4> <img src="/static/img/rb.jpeg" alt=""> <script src="/static/js/jquery-3.3.1.min.js"></script> <script src="/static/js/my.js"></script> </body> </html>
综上,在配置完settings.py
后,全部的静态文件路径均可以采用别名/static/
做为起始,这在必定程度上会有利于程序的扩展性,但若是咱们在项目后期维护时,连/static/
这个值也须要修改,那意味着全部模板文件中也都须要跟着改了,扩展性依然不好,为此,django
在一个名为static.py
的文件中定义了标签static
、get_static_prefix
,两者均可以解决该问题
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!--注意:必须先加载文件static.py--> {% load static %} <!--注意:此处的static是一个定义在static.py中的一个标签,名字与文件名同样而已,不要搞混--> <link rel="stylesheet" href="{% static 'css/my.css' %}"> </head> <body> <h4>我是红色的,点我就绿</h4> <img src="{% static 'img/rb.jpeg' %}" alt=""> {% load static %} <script src="{% static 'js/jquery-3.3.1.min.js' %}"></script> <script src="{% static 'js/my.js' %}"></script> </body> </html>
标签static
会接收传入的参数,而后这根据settings.py
中变量STATIC_URL
的值拼接出一个完整的路径,若是STATIC_URL = '/static/'
,那么href="{% static 'css/my.css' %}"
会被渲染成href="/static/css/my.css"
,若是STATIC_URL = '/static123/'
,那么href="{% static 'css/my.css' %}"
会被渲染成href="/static123/css/my.css"
。
标签get_static_prefix
也能够完成一样的效果,只不过用法不一样。咱们不能为标签get_static_prefix
传参,由于标签get_static_prefix
表明的只是settings.py
中STATIC_URL
的值,因此咱们须要作的是在get_static_prefix
的基础上自行拼接路径,以下
test.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!--注意:一样须要先加载文件static.py--> {% load static %} <!--使用标签get_static_prefix拼接路径--> <link rel="stylesheet" href="{% get_static_prefix %}css/my.css"> </head> <body> <h4>我是红色的,点我就绿</h4> <img src="{% get_static_prefix %}img/rb.jpeg" alt=""> {% load static %} <script src="{% get_static_prefix %}js/jquery-3.3.1.min.js"></script> <script src="{% get_static_prefix %}js/my.js"></script> </body> </html>
若是STATIC_URL = '/static/'
,那么href="{% get_static_prefix %}css/my.css"
会被渲染成href="/static/css/my.css"
,其它同理