MTV设计模式
Django
框架接收了用户请求和参数后,通过正则表达式匹配URL
,转发给对应视图views
进行处理,视图调用模型models
处理数据,再调用模板templates
返回界面给浏览器。
-
Models
:用来构建和操作web应用中的数据
- 继续讲解
models
之前,必须说下对象关系映射(Object Relational Mapping,简称ORM),ORM
使用对象和数据库建立映射,即将程序中的对象自动持久化到关系数据库中。ORM
是业务逻辑层和数据库层之间的桥梁。 - 在
Django
项目的settings.py
文件中,配置数据库连接信息,包括数据库名称等信息。之后,通过models
实现对数据库表的操作和数据存储。通常每个model
对应数据库中唯一的一张表,关于ORM
和数据库表的关系如下图。
ORM和数据库表关系
-
Views
:用于封装负责处理用户请求及返回响应的逻辑
-
Views
可以看作是前端页面与数据库的中间人,它会将前端想要的数据从数据库中读出来给前端,也会将用户要想保存的数据写到数据库。
-
Templates
:使用模板可以动态地生成html
- 模板包含所需html输出的静态部分
- 同时,模板语法可以描述如何将动态内容插入到html页面中。
MTV实例
- 目标是通过分页功能来理解Django中MTV工作模式,并熟悉模板语言的使用。
- 在开始分页功能之前,先来学习一个概念:上下文(context),上下文会在render函数中使用。其实render函数其主要作用是将给定的模板与给定的上下文字典组合在一起,并以渲染的文本返回一个
HttpResponse
对象。 - 一般来说,render函数常用的参数有三个(实际不止三个)
- request,用于生成此响应的请求对象
- template_name,要使用的模板的全名或模板名称的序列
- context,要添加到模板上下文的值的字典。 默认情况下,这是一个空的字典。 如果字典中的值是可调用的,则视图将在渲染模板之前调用它。简单来说,context参数就是把数据库中要在网页显示的内容读取,然后填充到模板中动态显示。

- 看一个render函数示例
def index(request):
context = {
'title': 'Context-Test',
'description': 'Just some words.'
}
return render(request, 'index.html', context)
对应templates中的html代码如下:
<li>
<img src="{% static 'images/0002.jpg' %}" width="100" height="90">
<h3><a href="#">{{ title }}</a></h3>
<p>{{ description }}</p>
</li>
这样在views调用teplates的时候就会加载context中内容,如果把context与数据库结合使用,那么就可以动态加载数据
- 理解了context功能之后,接下里要考虑如何从数据库获取数据来。这个时候就用到来models。如开头所讲models相当于数据库的代理,它对数据进行操作。以mongoDB为例,首先需要在settings.py中配置数据库信息:
from mongoengine import connect
connect(database_name, host='127.0.1', port=27017)
- 现在根据第一部分介绍的ORM,建立数据模型
# 定义一个类
class ArtiInfo(Document):
# 类的属性(collection中的字段名),右侧是字段类型
description = StringField()
title = StringField()
# 在数据库中创建一个collection,名为arti_info
meta = {
'collection': 'arti_info'
}
ArtiInfo对象每一个实际是collection中的一行数据,例如:
for item in ArtiInfo.objects:
print(item.title, item.description)
输出的结果就是数据表collection中每行数据
-
对应的在views中修改代码可以使得数据填充到templages构成的页面上下文中,但是因为页面结构的限制,我们需要对数据进行分页保证页面的样式不被破坏,这里需要使用到Django提供的分页器类Paginator,基本知识可参考这里
-
在views中使用Paginator类(Paginator Django 用法可参考如下代码),修改后如下:
def index(request):
# 设置页面每页显示的数据数目
limit = 4
# 获取数据对象构成的列表
arti_info = ArtiInfo.objects
# 构建分页器对象
paginator = Paginator(arti_info, limit)
# 设置request请求中GET方式的参数,这个参数是字典格式数据,即page默认为1
# www.google.com?thisIsAGetVarKey=3&thisIsAnotherOne=hello
# request.GET would be: {"thisIsAGetVarKey": 3, "thisIsAnotherOne":"hello"}
# Because request.GET is a dictionary,
# it has the method .get() which retrieves a value for a key in the dictionary
page = request.GET.get('page', 1)
# 获取某个页面对象,可调用相关方法和属性,包括数据和页面等信息
loaded = paginator.page(page)
context = {
'ArtiInfo': loaded,
}
return render(request, 'index.html', context)
关于page = request.GET.get('page', 1)
,可以解释为寻找名为page
的GET
参数,而且如果参数没有提交,返回1
,详细解释可参考这里。
- 接下里使用模板语言修改templates对应的代码,是的数据正常动态显示
{% if ArtiInfo.has_previous %}
<a href="?page={{ ArtiInfo.previous_page_number }}"> < Pre </a>
{% endif %}
<spam> {{ ArtiInfo.number }} of {{ ArtiInfo.paginator.num_pages }} </spam>
{% if ArtiInfo.has_next %}
<a href="?page={{ ArtiInfo.next_page_number }}"> Next > </a>
{% endif %}
网友评论