转载请注明来源地址和原做者(CFishHome)html
本篇文章将介绍模板相关的内容,例如:DTL模板语法(变量、模板标签、过滤器、自定义过滤器)。只要一步一步跟着一块儿操做,我相信模板这一块的内容毫无难度,就好像学习MarkDown同样好学好用。在此,由于前不久学校有不少事要处理,因此学习笔记耽搁了几天,趁国庆好好补补落下的内容,还有本篇DTL语法涉及众多,因此决定分上中下篇来说解和总结。html5
咱们先建立一个名为my_template的新Django项目。由于这篇内容涉及的是模板内容,跟app关系不大,因此在这里我就不建立一个app来进行URL映射了,而是直接在my_template主包
里添加一个views.py文件进行URL映射。总体框架以下图所示:
(1)为views.py添加如下代码:python
from django.http import HttpResponse def index(request): return HttpResponse("首页")
(2)修改urls.py代码以下:django
from django.urls import path from . import views urlpatterns = [ path('', views.index, name="index") ]
运行项目,能成功访问127.0.0.1:8000,好了学前工做准备完毕,下面正式进入模板的学习。浏览器
在前面的学习中,咱们编写的视图函数只是直接返回文本,例如:HttpResponse("首页"),而在实际生产环境中其实不多这样用,由于实际的页面大可能是带有样式的HTML代码,这可让浏览器渲染出很是漂亮的页面。目前市面上有很是多的模板系统,其中最知名最好用的就是DTL和Jinja2。 DTL 是 Django Template Language 三个单词的缩写,也就是Django自带的模板语言。固然也能够配置Django支持Jinja2等其余模板引擎,可是做为Django内置的模板语言,和Django能够达到无缝衔接而不会产生一些不兼容的状况。所以建议你们学习好DTL。
如今总结下概念,为后面的学习作准备:app
DTL(Django Template Language )名叫Django模板语言,用DTL编写的是一个DTL模板文件,这个文件是一个带有特殊语法的HTML文件,利用pycharm建立一个Django项目,那么会自动生成一个template文件夹,这个文件夹就是存放项目的DTL模板文件(也就是带有特殊语法的HTML文件)。在视图函数里面能够利用render_to_string方法将指定的DTL模板文件编译后渲染成Python的字符串格式,而后用HttpResponse方法打包返回给客户端,或者在视图函数里面直接利用render方法将指定的DTL模板文件渲染接着自动打包成HttpResponse,而后视图函数返回给客户端。框架
渲染模板有多种方式。这里讲下两种经常使用的方式。
(1) render_to_string:该函数会自动在templates文件夹搜寻DTL模板文件,找到后接着将DTL模板文件编译后渲染成Python的字符串格式。最后再经过HttpResponse类包装成一个HttpResponse 对象返回回去。
1.修改views.py代码以下:ide
from django.template.loader import render_to_string from django.http import HttpResponse def index(request): html = render_to_string("index.html") # 该函数在templates文件夹搜寻是否含有index.html文件,找到后将该文件(DTL模板文件)编译后渲染成Python的字符串格式 return HttpResponse(html) # 而后将html经过HttpResponse包装后返回给浏览器进行显示
2.templates文件夹就是专门存放DTL模板文件的,在工程目录中能够找到这个文件夹。而后在templates文件夹下添加index.html文件,以下图所示:
3.添加index.html后,默认会生成一些html5的代码,接着咱们修改该文件,在浏览器中显示一段文字:
4.运行Django项目,而后输入127.0.0.1:8000,显示结果以下(成功访问到了咱们渲染的模板文件index.html):
(2)以上方式虽然已经很方便了。可是django还提供了一个更加简便的方式-render方法(推荐该方式),直接将模板渲染成字符串和包装成 HttpResponse 对象一步到位完成。
1.在前一个测试render_to_string方法的代码基础上,修改views.py文件代码以下:函数
from django.shortcuts import render from django.http import HttpResponse def index(request): return render(request, "index.html") # render方法很方便,只要第一个参数指定request对象,第二个参数指定模板文件的路径,而后它会自动在templates文件夹下搜寻该文件,而后自动渲染再用HttpResponse包装返回。
按下Ctrl+S保存,输入127.0.0.1:8000,显示结果以下(再次成功访问到了咱们渲染的模板文件index.html):
2.分析render函数的内部实现,源代码以下图:
从上图能够看出,其实render方法内部也是调用render_to_string渲染、HttpResponse包装再返回,直接使用render方法减轻了咱们对代码的编写,而且让代码更美观简洁,嗯~的确不错。学习
上一小节我介绍了如何渲染模板,其中render或render_to_string方法有一个参数是指定DTL模板文件,而后在templates文件夹下查找指定的DTL模板文件。其实,对于DTL模板文件有一个专门的查找路径,允许我一一道来。在项目的 settings.py 文件中。有一个 TEMPLATES 配置,这个配置包含了模板引擎的配置,模板查找路径的配置等。以下图所示:
这个TEMPLATES配置里面有两个重要的属性:DIRS、APP_DIRS。DTL模板文件查找路径能够经过这两个属性配置。
(1) DIRS :这是一个列表,在这个列表中能够存放全部的DTL模板文件路径,之后在视图中使用 render 或者 render_to_string 渲染模板的时候,会在这个列表的路径中查找模板。通常状况下是“os.path.join(BASE_DIR, 'templates')”,os.path.join()函数是将BASE_DIR和‘templates’拼接,其中BASE_DIR是当前项目的路径,注意,不论项目被移动到哪一个目录下,BASE_DIR都会动态修改当前项目的路径,怎么实现动态?同样定位到settings.py文件前面的代码,以下图:
意思是说不管将项目放到哪里,利用render等函数渲染模板时,均可以找到templates目录下的DTL模板文件,由于BASE_DIR和‘templates’拼接起来其实就是templates文件夹的绝对路径。
(2)APP_DIRS :默认为 True ,这个设置为 True 后,若是在DIRS指定的模板查找路径不能找到模板文件,那么就会在 INSTALLED_APPS 安装了的APP下的 templates 文件加中查找模板。同样定位到settings.py文件前面的代码,以下图(默认安装了一些Django项目必须的app):
这个APP_DIRS的做用是当DIRS不能找到模板文件时,就在其余app上查找模板,须要进行如下两步:1.在INSTALLED_APPS添加app的名字。例如:"front"。2.在app目录下建立一个名为templates的文件夹(必须是这个名字,其余不容许),而后添加DTL模板文件。那么当DIRS找不到时就跑这个app里的templates目录找模板。
DTL模板文件查找顺序:好比代码 render('list.html') 。先会在 DIRS 这个列表中依次查找路径下有没有这个模板,若是有,就返回。若是 DIRS 列表中全部的路径都没有找到,那么会先检查当前这个视图所处的 app (什么叫当前这个视图所在的app?其实就是假如views.py在front这个app目录下,那么front就是当前这个视图所处的app。) 是否已经安装,若是已经安装了,那么就先在当前这个 app 下的 templates 文件夹中查找模板,若是没有找到,那么会在其余已经安装了的 app 中查找。若是全部路径下都没有找到,那么会抛出一个 TemplateDoesNotExist 的异常。
模板中能够包含变量, Django 在渲染模板的时候,能够传递变量对应的值过去进行替换。变量的命名规范和 Python 很是相似,只能是阿拉伯数字和英文字符以及下划线的组合,不能出现标点符号等特殊字符。变量须要经过视图函数渲染,视图函数在使用 render 或者 render_to_string 的时候能够传递一个 context 的参数,这个参数是一个字典类型。之后在模板中的变量利用{{变量名}}从这个字典中读取值的。
举个变量的栗子:
(1)修改views.py代码以下(添加context参数来为DTL模板文件传递变量):
from django.shortcuts import render from django.http import HttpResponse def index(request): context = { "username": "CFishHome学习" } return render(request, "index.html", context=context) # 函数指定关键字参数context来传递变量
(2)修改index.html模板的代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CFishHome</title> </head> <body> {{ username }} </body> </html>
按下Ctrl+S保存,注意要在python文件保存,在index.html下保存不能自动从新运行。运行结果以下:
事实上,context字典键通常为变量名(字符串类型),而值有多种类型,其中包括前面列举的字符串、字典、元组、列表、类对象、函数名等。下面一一举例测试经常使用的几种变量类型的使用,字符串类型前面已列举,这里再也不演示:
(1)字典
与Python语法不一样的是,DTL语法不容许经过中括号的形式访问字典或列表中的值,好比dict['key']和list[1]是不支持的!不要问为何,规则是那些大牛们定下来的,咱们只能遵循他们定下的规则。
修改views.py代码以下:
from django.shortcuts import render from django.http import HttpResponse def index(request): context = { "book": { "book_id": "A001", "book_name":"人民的名义", "book_price":1000 } } return render(request, "index.html", context=context)
修改index.html代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CFishHome</title> </head> <body> <p>{{ book.book_id }}</p> <p>{{ book.book_name }}</p> <p>{{ book.book_price }}</p> </body> </html>
按下Ctrl+S保存,运行结果以下(成功访问字典的键所对应的值):
由于字典可使用点(.)语法获取字典键所对应的值,而且也可使用点(.)语法调用字典内置的方法,因此在给这个字典添加key的时候,千万不能和字典中的一些属性或方法重复。好比items,items是字典的方法,那么若是给这个字典添加一个items做为key,那么之后就不能再经过item来访问这个字典的键值对了,而是变成访问咱们自定义的items键所对应的自定义的值了。下面举个栗子:
1.经过{{ 变量名.函数名 }}就能够调用该变量对应的函数了,修改index.html代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CFishHome</title> </head> <body> <p>{{ book.book_id }}</p> <p>{{ book.book_name }}</p> <p>{{ book.book_price }}</p> <p>{{ book.keys }}</p> </body> </html>
运行结果以下,经过字典内置的keys方法,成功访问到了该字典含有的全部键:
2.修改views.py文件的context内容,添加与字典内置函数Keys冲突的keys键和对应的值,代码以下:
from django.shortcuts import render from django.http import HttpResponse def index(request): context = { "book": { "book_id": "A001", "book_name": "人民的名义", "book_price": 1000, "keys": 200 } } return render(request, "index.html", context=context)
按下Ctrl+S保存,运行结果以下:
从上图能够看出,咱们自定义的与字典内置函数keys冲突的keys键被解析显示在页面上,可是字典内置函数keys永远都执行不到了,由于被覆盖了。因此在此提个建议:给字典添加key的时候,千万不能和字典中的一些属性或方法重复,否则会被覆盖。
(2)列表或者元组
若是book是一个列表或者元组,是不能经过中括号的形式访问列表和元组中的值,好比list[1]是不支持的!只可以经过'.'来访问。
1.修改views.py文件的context内容,代码以下:
from django.shortcuts import render from django.http import HttpResponse def index(request): context = { "book": ["水浒传", "人民的名义", "鲁迅自传", "钢铁是怎样炼成的"], "price": (100, 200, 300, 400) } return render(request, "index.html", context=context)
2.经过{{ 变量名.下表 }}就能够访问该变量对应的元素值了,修改index.html代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CFishHome</title> </head> <body> <p>{{ book.0 }}</p> <p>{{ book.1 }}</p> <p>{{ book.2 }}</p> <p>{{ book.3 }}</p> <p>{{ price.0 }}</p> <p>{{ price.1 }}</p> <p>{{ price.2 }}</p> <p>{{ price.3 }}</p> </body> </html>
按下Ctrl+S保存,运行结果以下:
(3)类对象
若是book是一个对象,那么就会能够在模板访问这个对象的属性,或者是方法。
1.修改views.py文件的context内容,代码以下:
from django.shortcuts import render from django.http import HttpResponse class A: def __init__(self, count): self.count=count def show(self): print("我是一个类") def index(request): a = A(100) context = { "book": a } return render(request, "index.html", context=context)
2.经过{{ 变量名.属性或者函数名 }}就能够访问该对象对应的属性或调用对应的函数了,修改index.html代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CFishHome</title> </head> <body> <p>{{ book.show }}</p> <p>{{ book.count }}</p> </body> </html>
按下Ctrl+S保存,运行结果以下:
由上可得出,在DTL模板文件成功访问到对象的属性,第一个输出的是None,由于只是单纯的调用(输出信息在下图所示控制台)。
(4)函数
book也能够是一个函数名(例如:show或show()),表明这个函数,在DTL模板文件中引用时也是{{ 变量名 }}方式调用函数,须要注意的是这种方式是没法传递函数参数的,因此这个函数在定义时写参数也没用。
1.修改views.py文件的context内容,代码以下:
from django.shortcuts import render from django.http import HttpResponse def show(): print("我是一个简单的函数") def index(request): context = { "book": show } return render(request, "index.html", context=context)
2.经过{{ 变量名.函数名 }}就能够访问该函数了,修改index.html代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>CFishHome</title> </head> <body> <p>{{ book.show }}</p> </body> </html>
按下Ctrl+S保存,运行结果以下:
建立了一个Django项目,可是运行时报错可能会报下面这个错误:
为何会报这个错误?其实就是端口被占用了,那以我目前这个电脑程序运行状况举例,我开机->打开酷狗(听音乐)->打开pycharm->建立Django项目(默认使用8000端口)->运行项目->报端口占用错误。
咱们打开CMD执行如下命令:
第一条命令找出8000端口对应的PID进程为2032,第二条命令经过进程ID找出进程对应的详细信息,能够看到这个进程对应的是酷狗服务。问题找到了,就是由于咱们先开启了酷狗,酷狗服务占用了咱们的测试端口。因此解决办法有两个:
1.关闭酷狗再从新运行Django项目。
2.将Django项目的测试端口改成其余,例如:9000