模板介绍和渲染模板
Django模板的介绍
•我们在前面使用Django时,视图函数返回的只是文本,而在实际开发应用中其实很少这样使用,而是返回带有样式的HTML代码
,这样可以让浏览器渲染出美观的页面,供用户使用
•DTL即Django Template Language
,是指Django框架自带的模板语言,使用一种带有特殊语法的HTML文件,可以被Django编译,还可以传递参数、实现数据动态化。在编译完成后,生成一个普通的HTML文件,然后发送给客户端进行渲染显示
•Django框架同时也支持配置Jinja2等其他模板
引擎,但是DTL作为Django内置的模板语言,DTL可以和Django达到无缝衔接、不会产生不兼容的情况,前提是不采用前后端分离的开发模式
模板渲染
•模板渲染的有多种不同方式,主要包括以下两种:
•django.template.loader.render_to_string
根据配置的模板路径和传入的模板名称寻找模板,然后将模板编译后渲染成HTML字符串,再通过HttpResponse类包装成一个HttpResponse对象返回
•django.shortcuts.render
这是一种更加简便的方式,直接将模板渲染成字符串并包装成HttpResponse对象一步完成。render()方法
其实也是调用的render_to_string()方法
,只不过又进行了一次封装,因此使用起来也更加方便
•第一种方式测试如下:
•先通过命令django-admin startproject django_template
新建项目django_template
,并进入项目目录,然后通过命令python manage.py startapp book
创建名为book的app
•首先在项目目录下新建模板目录templates
,在模板目录下新建book.html
如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>Django模板测试</p>
</body>
</html>
•然后在项目目录下的settings.py
中定义模板路径如下:
import os
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',
],
},
},
]
注意:一定要导入os模块
•book app的views.py如下:
from django.http import HttpResponse
from django.template.loader import render_to_string
def index(request): # 第一种方法
html = render_to_string('book.html')
return HttpResponse(html)
•book目录下新建urls.py如下:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index)
]
•项目目录下的urls.py文件:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', include('book.urls'))
]
注意:
•按照以上顺序即可成功的渲染模板,注意在settings.py文件中一定要导入os模块
•Django框架
中支持自定义模板路径,不一定是templates目录、可以自定义模板路径,只要在DIRS列表中添加路径即可
•网页显示:
•从网页结果显示可以看出来 模板已经被成功渲染
•第二种方式测试如下:
•book app的views.py如下:
from django.http import HttpResponse
from django.shortcuts import render
from django.template.loader import render_to_string
def index(request): # 第一种方法
html = render_to_string('index.html')
return HttpResponse(html)
def book(request): # 第二种方法
return render(request, 'books.html')
•在模板目录下新建books.html
如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>Django模板测试2</p>
</body>
</html>
•book目录下的urls.py文件如下:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('books/', views.book)
]
•网页显示如下:
•由上面可以看出,第二种方法更加方便,我们以后在日常开发中会使用更多
•其实还有一种方式render_to_response()
,这与render()
方法类似,只是增加了warnings.warn()
方法,其源码如下:
def render_to_response(template_name, context=None, content_type=None, status=None, using=None):
"""
Return a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
warnings.warn(
'render_to_response() is deprecated in favor of render(). It has the '
'same signature except that it also requires a request.',
RemovedInDjango30Warning, stacklevel=2,
)
content = loader.render_to_string(template_name, context, using=using)
return HttpResponse(content, content_type, status)
•render()
方法源码如下:
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Return a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
查找模板路径的配置
•前面使用模板是在settings.py
中配置模板路径,给DIRS变量
添加具体路径到列表即可
•以上配置是在TEMPLATES变量
中进行的,这个配置包含了模板引擎、模板查找路径、模板上下文等
•模板文件的路径可以在两个地方配置:
•DIRS
DIRS是一个列表,在这个列表中可以存放所有的模板路径,在视图中使用render或者render_to_string渲染模板的时候,会在这个列表的路径中查找模板的具体位置进行渲染
•APP_DIRS
默认为True,设置为True后,会在项目目录下的settings.py文件
中的INSTALLED_APPS
中已经注册的APP下的templates目录中查找模板
如果要使用APP_DIRS这种配置方法,只需要在项目目录下的settings.py文件
中的INSTALLED_APPS
列表中添加相应的app名字进行注册
模板查找顺序
•比如现在有一个模板index.html,并且要在视图函数中将其作为参数进行渲染,查找此模板的顺序如下:
首先会在DIRS列表中依次查找路径下有没有该模板,如果有则返回
如果DIRS列表中所有的路径都没有找到,那么会先检查当前这个视图所处的app是否已经在INSTALLED_APPS
中注册,如果已经注册,那么就先在当前这个app下的templates文件夹中查找模板
如果还是没有找到,那么会在其他已经注册了的app中查找模板
如果所有路径下都没有找到,会抛出TemplateDoesNotExist异常
测试如下:
•book app的views.py如下:
from django.http import HttpResponse
from django.shortcuts import render
from django.template.loader import render_to_string
def index(request):
html = render_to_string('index.html')
return HttpResponse(html)
def book_list(request):
return render(request, 'booklist.html')
def book_detail(request):
return render(request, 'bookdetail.html')
•book app的urls.py定义路由如下:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('booklist/', views.book_list),
path('bookdetail/', views.book_detail),
]
•在项目目录下settings.py注册app如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'book'
]
•在book app下新建templates目录,新建booklist.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>莫问前程</p>
</body>
</html>
•项目目录下的templates目录新建bookdetail.html文件如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>但行好事</p>
</body>
</html>
•网页测试如下:
•在访问http://127.0.0.1:8000/book/booklist时查找booklist.html
先在项目DIRS指定的模板目录即项目模板目录中查找,查找到直接渲染
•访问http://127.0.0.1:8000/book/bookdetail时,bookdetail.html在项目模板目录中未查找到,则到INSTALLED_APPS目录
中查找,查找到后进行渲染
DTL模板变量
•模板中可以包含变量,以保证Django框架在渲染模板的时候可以传递变量对应的值进行替换,以实现动态显示
•模板变量的命名规范和Python类似,包括只能是阿拉伯数字和英文字符以及下划线的组合、不能出现标点符号等特殊字符等
•变量需要通过视图函数传递到模板进行渲染,和Flask框架中的用法类似,视图函数在调用render
或者render_to_string
时指定context参数实现参数传递,context参数类型为字典
•测试如下:
•book app下的views.py如下:
from django.http import HttpResponse
from django.shortcuts import render
from django.template.loader import render_to_string
def index(request):
html = render_to_string('index.html')
return HttpResponse(html)
def book_list(request):
return render(request, 'booklist.html', context={'name': 'Python从入门到入土'})
def book_detail(request):
return render(request, 'bookdetail.html')
•templates/booklist.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>图书列表</p>
<p>图书名称:{{ name }}</p>
</body>
</html>
•网页显示如下:
•测试各种变量进行传参
•book app下的views.py如下:
from django.http import HttpResponse
from django.shortcuts import render
from django.template.loader import render_to_string
def index(request):
html = render_to_string('index.html')
return HttpResponse(html)
class Person(object):
def __init__(self, username):
self.username = username
def book_list(request):
context = {
'username': 'Ycx',
'books': ['Python', 'Java', 'PHP'],
'authors': ('Jack', 'Tom', 'Cbh'),
'info': {
'name': 'Django'
},
'person': Person('CH')
}
return render(request, 'booklist.html', context=context)
def book_detail(request):
return render(request, 'bookdetail.html')
•templates/booklist.html如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>用户名:{{ username }}</p>
<p>图书列表</p>
<p>{{ books.0 }}</p>
<p>{{ books.1 }}</p>
<p>{{ books.2 }}</p>
<p>作家列表</p>
<p>{{ authors.0 }}</p>
<p>{{ authors.1 }}</p>
<p>{{ authors.2 }}</p>
<p>信息</p>
<p>{{ info.name }}</p>
<p>类</p>
<p>{{ person.username }}</p>
<p>{{ person.email }}</p>
</body>
</html>
•网页显示:
•由上可得:
•如果取不到值会不显示,也不会报错,这是因为未匹配到时会返回空字符串。
•如果参数是列表、元组、字典等类型,直接使用点号.
调用的,模板是按照以下方式进行解析的
•如果变量是一个列表或元组,会根据数字索引查找相应的值
•如果变量是一个字典,那么就会查找key对应的值
•如果变量是一个对象,那么就会查找这个对象的相应属性
或者方法
•不能通过中括号[]
的形式访问字典和列表中的值,比如 info[‘name’] 和 books[1] 是获取不到值的
注意
•使用点号.
语法获取对象值的时候,可以获取这个对象的属性,如果这个对象是一个字典,也可以获取这个字典的值,所以在视图函数中给字典添加key的时候,命名不能和字典中的一些属性重复
• 比如items是字典自带的方法,那么如果给这个字典添加一个items作为key,以后就不能再通过items来访问这个字典的键值对