截至目前,通过下列几篇文章,针对遵循MVT
模式的Django,我们已经做了如下学习:
MVT
和MVC
两种设计模式的异同,并知道了Django遵循所谓的MVT
模式,该模式将框架分为三个模块:M
(模型)、V
(视图)、T
(模板);为了对Django的M
、V
、T
三个模块有一个整体的认识,本文使用下列文章中已有的基础实现一个综合案例:
booktest
;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
。
由于视图函数主要负责从模型处获取数据,将数据给到特定的模板进行渲染后返回用户展示,因此首先需要设计如下视图函数:
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})
V
(视图)通过M
(模型)获取的数据需要给到T
(模板)进行渲染,则模板文件编写如下:
<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>
为确保通过浏览器访问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
:
为了实现需求# 2
,需要为实现需求# 1
后显示出的图书标题添加超链接,这可以通过在show_books.html
中为图书标题添加标签并使用其
href
属性实现:
<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
作为图书的唯一标识,从而获取该图书下所有英雄的记录。
下面定义一个处理该请求的视图函数,命名为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}
)
通过模板文件,将使用模型类查询得到的数据进行渲染:
<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>
在点击带有超链接的图书名称后,为了确保框架可以通过一个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
,并点击一条记录后,可以实现浏览器的访问效果如下:
天龙八部
英雄信息如下:
- 段誉----六脉神剑
- 乔峰----降龙十八掌
- 虚竹----天山折梅手
至此,实现了本文所提出的的需求。