截至目前,通过下列几篇文章,针对遵循MVT
模式的Django,我们已经做了如下学习:
- 【Django入门】——MVC和MVT两种模式的异同:了解了
MVT
和MVC
两种设计模式的异同,并知道了Django遵循所谓的MVT
模式,该模式将框架分为三个模块:M
(模型)、V
(视图)、T
(模板); - 【Django入门】——Django中通过模型类实现数据表基本操作:通过案例了解了如何使用模型模块操作数据库;
- 【Django入门】——Django中视图函数和模板文件的使用:通过案例了解了如何使用视图和模板模块响应并返回浏览器的请求。
为了对Django的M
、V
、T
三个模块有一个整体的认识,本文使用下列文章中已有的基础实现一个综合案例:
- 【Django入门】——从零开始创建并启动一个Django项目,使用其中创建的应用
booktest
; - 【Django入门】——Django中通过模型类实现数据表基本操作,使用其中创建的模型类
BookInfo
、HeroInfo
及其分别对应的数据表booktest_bookinfo
和booktest_heroinfo
,且:
booktest_bookinfo
数据表中所有记录为:
id | book_title | book_pub_date |
---|---|---|
2 | 天龙八部 | 1960-01-01 |
3 | 射雕英雄传 | 2017-12-13 |
booktest_heroinfo
数据表中所有记录为:
id | hero_name | hero_gender | hero_desc | hero_book_id |
---|---|---|---|---|
1 | 段誉 | 0 | 六脉神剑 | 2 |
2 | 乔峰 | 0 | 降龙十八掌 | 2 |
3 | 虚竹 | 0 | 天山折梅手 | 2 |
该综合案例的需求为:
# 1.
在本机浏览器上输入127.0.0.1:8000/books
时,浏览器显示booktest_bookinfo
表中所有记录的book_title
字段值:
图书信息如下:
- 天龙八部
- 射雕英雄传
# 2.
当进一步点击图书标题时,则按照规则进一步显示对应图书中所有英雄的hero_name
和hero_desc
字段值。
一、案例初步实现
首先实现需求# 1
,然后再实现# 2
。
1. 设计视图函数
由于视图函数主要负责从模型处获取数据,将数据给到特定的模板进行渲染后返回用户展示,因此首先需要设计如下视图函数:
from django.shortcuts import render
from booktest.models import BookInfo # 导入图书模型类
# Create your views here.
def show_books(request):
"""显示图书信息"""
# 1. 通过M(模型)查找图书表booktest_bookinfo中的所有数据
books = BookInfo.objects.all()
# 2. 使用T(模板文件),返回结果给浏览器
return render(request=request,
template_name='booktest/show_books.html',
context={'books': books})
2. 模板文件编写
V
(视图)通过M
(模型)获取的数据需要给到T
(模板)进行渲染,则模板文件编写如下:
<!-- show_books.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示图书信息</title>
</head>
<body>
图书信息如下:
<ul>
{%for book in books%}
<li>{{book.book_title}}</li>
{%endfor%}
</ul>
</body>
</html>
3. 配置路由URL
为确保通过浏览器访问127.0.0.1:8000/books
时,框架可以正确路由处理该URL,需要分别在项目和应用的urls.py
文件中做对应配置:
- 配置应用的
urls.py
文件:
# booktest.urls.py
from django.conf.urls import url
from booktest import views
# 建立URL地址和视图之间的对应关系
urlpatterns = [
# 通过url函数设置url路由配置项
url(r'^books$', views.show_books)
]
- 配置项目的
urls.py
文件:
# test1.urls.py
from django.conf.urls import url, include
from django.contrib import admin
# 包含booktest应用中的urls文件
urlpatterns = [
url(r'^admin/', admin.site.urls), # 配置项目
url(r'^', include('booktest.urls')),
]
二、案例完整实现
上面实现了该综合案例的需求# 1
,下面实现需求# 2
:
1. 添加超链接
为了实现需求# 2
,需要为实现需求# 1
后显示出的图书标题添加超链接,这可以通过在show_books.html
中为图书标题添加<a></a>
标签并使用其href
属性实现:
<!-- show_books.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示图书信息</title>
</head>
<body>
图书信息如下:
<ul>
{%for book in books%}
<li><a href="books/{{book.id}}">{{book.book_title}}</a></li>
{%endfor%}
</ul>
</body>
</html>
需要说明的是,这里通过一条图书记录的主键id
作为图书的唯一标识,从而获取该图书下所有英雄的记录。
2. 设计视图函数
下面定义一个处理该请求的视图函数,命名为show_details()
:
# views.py
from django.shortcuts import render
from booktest.models import BookInfo # 导入图书模型类
......
def show_details(request, book_id):
"""查询在对应图书中的英雄的信息"""
# 1. 根据book_id查询图书信息
book = BookInfo.objects.get(id=book_id)
# 2. 查询和book关联的英雄信息
heroes = book.heroinfo_set.all()
# 3. 使用模板,将图书和英雄数据传入模板
return render(request=request,
template_name='booktest/hero_details.html',
context={'book': book, 'heroes': heroes}
)
3. 编写模板文件
通过模板文件,将使用模型类查询得到的数据进行渲染:
<!-- hero_details.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>显示图书关联的英雄信息</title>
</head>
<body>
<h1>{{book.book_title}}</h1>
英雄信息如下:<br/>
<ul>
{%for hero in heroes%}
<li>{{hero.hero_name}}----{{hero.hero_desc}}</li>
{%endfor%}
</ul>
</body>
</html>
4. 配置路由URL
在点击带有超链接的图书名称后,为了确保框架可以通过一个url找到某一个视图函数来处理该请求,则需要配置booktest
应用的urls.py
文件。
from django.conf.urls import url
from booktest import views
# 进行URL配置,建立URL地址和视图之间的对应关系
urlpatterns = [
# 通过url函数设置url路由配置项
url(r'^books$', views.show_books),
url(r'^books/(\d+)$', views.show_details)
]
需要注意的是,上述对正则的一部分\d+
使用()
进行分组(关于正则中的分组等概念,请见文章Python爬虫、后端,使用正则表达式,看这一篇就够了!),可以保证通过该部分匹配出的结果可默认传递给show_details()
函数的book_id
形参。
此时,如果通过访问127.0.0.1:8000/books
,并点击一条记录后,可以实现浏览器的访问效果如下:
天龙八部
英雄信息如下:
- 段誉----六脉神剑
- 乔峰----降龙十八掌
- 虚竹----天山折梅手
至此,实现了本文所提出的的需求。