目录
一、模板
创建模板文件
定义模板
视图调用模板
简写视图调用的模板
二、去除模板中的硬编码 URL
三、为 URL 名称添加命名空间
四、生成模板渲染后的静态文件
源码等资料获取方法
一、模板
如何向请求者返回一个漂亮的页面呢?
肯定需要用到html、css,如果想要更炫的效果还要加入js,问题来了,这么一堆字段串全都写到视图中,作为HttpResponse()的参数吗?这样定义就太麻烦了吧,因为定义字符串是不会出任何效果和错误的,如果有一个专门定义前端页面的地方就好了。
解决问题的技术来了:模板。
在Django中,将前端的内容定义在模板中,然后再把模板交给视图调用,各种漂亮、炫酷的效果就出现了。
创建模板文件
在项目test1中新增templates目录,现在我们可以直接将模板放入 test1/templates
,但实际上并不建议这样做。Django会选择找到的第一个名称匹配的模板,如果在其他应用有一个具有相同名称的模板,Django则无法区分它们。我们需要Django能够指向正确的位置,而确保这一点的最佳方法是将这些模板放在应用程序本身命名的另一个目录中。目录结构如下图:
设置模板的查找路径:打开test1/settings.py文件,设置TEMPLATES的DIRS值
'DIRS': [os.path.join(BASE_DIR, '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',
],
},
},
]
定义模板
在模板中输出变量语法如下,变量可能是从视图中传递过来的,也可能是在模板中定义的。
{{变量名}}
在模板中编写代码段语法如下:
{%代码段%}
打开templtes/booktest/index.html文件,定义模板如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>图书列表</title>
<style>
td {text-align: center;}
</style>
</head>
<body>
<h1>{{title}}</h1>
<table width="500px">
<tr>
<th>书籍名称</th>
<th>发布日期</th>
</tr>
{%for book in books%}
<tr>
<td>{{book.btitle}}</td>
<td>{{book.bpub_date}}</td>
</tr>
{%endfor%}
</table>
</body>
</html>
视图调用模板
调用模板分为三步骤:
- 1.找到模板
- 2.定义上下文
- 3.渲染模板
打开booktst/views.py文件,调用上面定义的模板文件
from django.shortcuts import render
from booktest.models import BookInfo
from django.http import HttpResponse
from django.template import loader, RequestContext
# Create your views here.
def index(request):
# 1.获取模板
template=loader.get_template('booktest/index.html')
# 2.定义上下文
books = BookInfo.objects.all()
# context=RequestContext(request,{'title':'图书列表','books':books}) # 老版本
context = {'title': '图书列表', 'books': books}
# 3.渲染模板
# return HttpResponse(template.render(context)) # 老版本
return HttpResponse(template.render(context, request))
打开浏览器刷新页面,显示效果如下图:
简写视图调用的模板
视图调用模板都要执行以上三部分,于是Django提供了一个函数render封装了以上代码。 方法render包含3个参数:
- 第一个参数为request对象
- 第二个参数为模板文件路径
- 第三个参数为字典,表示向模板中传递的上下文数据
打开booktst/views.py文件,调用render的代码如下:
from django.shortcuts import render
from booktest.models import BookInfo
# Create your views here.
def index(request):
books = BookInfo.objects.all()
context = {'title': '图书列表', 'books': books}
return render(request, 'booktest/index.html', context) # 返回HttpResponse实例
二、去除模板中的硬编码 URL
在案例中的 test1/templates/booktest/index.html 文件里编写的链接都硬编码的链接,比如:
<a href="/booktest/search/{{book.id}}">查看英雄</a>
如果要将路径修改为searchHeroInfo,需要同时修改模板和路由才行。在一个包含很多应用的项目中,使用硬编码和强耦合的链接,修改起来是十分困难的。
我们可以将 booktest/urls.py 的路由改成如下代码:
...
# ex: /booktest/search/1
path('search/<int:bid>', views.hero_info, name='search')
...
- <int:bid> 表示正则方式匹配对应路径输入值,并将匹配结果转换成Int传给视图的第二个形参
- name 为路由反向代理的名称
然后,在 test1/templates/booktest/index.html 文件中使用 {% url 反向代理名称 %} 替换硬编码部分:
<a href="{% url 'search' book.id %}">查看英雄</a>
修改完后,如果要改变投票详情视图的 URL,比如改成 booktest/searchHeroInfo/1,那么就不用再修改模板中的任何代码(包括其它模板),只要在 booktest/urls.py 里修改一下就行:
# ex: /booktest/search/1
path('searchHeroInfo/<int:bid>', views.hero_info, name='search')
三、为 URL 名称添加命名空间
在一个真实的 Django 项目中,可能会有五个,十个,二十个,甚至更多应用。Django 如何分辨重名的 URL 呢?举个例子,booktest
应用有 search 视图,可能另一个应用也有同名的视图。Django 如何知道 {% url %}
标签到底对应哪一个应用的 URL 呢?
答案是:在根 URLconf 中添加命名空间。在 booktest/urls.py 文件中稍作修改,加上 app_name
设置命名空间:
from django.urls import path
from booktest import views
app_name = 'booktest'
urlpatterns = [
# ex: /booktest/ # 调用index视图函数
path('', views.index, name='index'),
# ex: /booktest/create # 调用create视图函数
path('create', views.create),
# ex: /booktest/delete/1
# re_path('delete/(\d+)', views.delete), # 在path中使用正则时需要导入re_path方法
path('delete/<int:bid>', views.delete, name='delete'), # bid为视图函数的的形参名
# ex: /booktest/search/1
path('searchHeroInfo/<int:bid>', views.hero_info, name='search')
]
现在,编辑 test1/templates/booktest/index.html 文件,从:
<a href="{% url 'search' book.id %}">查看英雄</a>
修改为指向具有命名空间的详细视图:
<a href="{% url 'booktest:search' book.id %}">查看英雄</a>
在视图函数中重定向时使用具有命名空间的视图,编辑 test1/booktest/views.py 文件,从:
def create(request):
book = BookInfo(btitle="流星蝴蝶剑", bpub_date=datetime.date(1995, 12, 30), bread=2, bcomment=1)
book.save()
return redirect("/booktest/")
修改为:
def create(request):
book = BookInfo(btitle="流星蝴蝶剑", bpub_date=datetime.date(1995, 12, 30), bread=2, bcomment=1)
book.save()
return redirect(reverse("booktest:index"))
若重定向的界面需要传个book.id参数,代码如下:
def create(request):
...
return redirect(reverse('booktest:index', args=(book.id,)))
四、生成模板渲染后的静态文件
render函数返回的是一个 HttpResponse 实例对象,要生成模板渲染后的静态文件,可按如下方式生成。
# 上下文
content = {
"good_types": good_types,
"good_banners": good_banners,
"promotion_banners": promotion_banners,
}
# 使用模板
# 1.加载模板文件,返回模板对象
temp = loader.get_template('index.html')
# 2.模板渲染
static_index_html = temp.render(content)
# 生成首页对应静态文件
save_path = os.path.join(settings.BASE_DIR, 'static/static_index.html')
with open(save_path, 'w', encoding="utf-8") as f:
f.write(static_index_html)
执行代码后,会在对应路径生成静态文件,静态文件中django自带的模板语法会被全部渲染成html文件
源码等资料获取方法
各位想获取源码的朋友请点赞 + 评论 + 收藏,三连!
三连之后我会在评论区挨个私信发给你们~