模型
之前,我们用 Django 建造网站的基本途径: 建立视图和 URLConf 。 正如我们所阐述的,视图负责处理一些主观逻辑,然后返回响应结果。 作为例子之一,我们的主观逻辑是要计算当前的日期和时间。
在当代 Web 开发中,主观逻辑经常牵涉到与数据库的交互。 数据库驱动网站在后台连接数据库服务器,从中取出一些数据,然后在 Web 页面用漂亮的格式展示这些数据。 这个网站也可能会向访问者提供修改数据库数据的方法。
许多复杂的网站都提供了以上两个功能的某种结合。 例如 Amazon.com 就是一个数据库驱动站点的良好范例。 本质上,每个产品页面都是数据库中数据以 HTML格式进行的展现,而当你发表客户评论时,该评论被插入评论数据库中。
由于先天具备 Python 简单而强大的数据库查询执行方法,Django 非常适合开发数据库驱动网站。
MTV 开发模式
在钻研更多代码之前,让我们先花点时间考虑下 Django 数据驱动 Web 应用的总体设计。
在前面提到过,Django 的设计鼓励松耦合及对应用程序中不同部分的严格分割。 遵循这个理念的话,要想修改应用的某部分而不影响其它部分就比较容易了。 在视图函数中,我们已经讨论了通过模板系统把业务逻辑和表现逻辑分隔开的重要性。 在数据库层中,我们对数据访问逻辑也应用了同样的理念。
把数据存取逻辑、业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的 Model-View-Controller(MVC)模式。 在这个模式中, Model 代表数据存取层,View 代表的是系统中选择显示什么和怎么显示的部分,Controller 指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分。
Django 紧紧地遵循这种 MVC 模式,可以称得上是一种 MVC 框架。 以下是 Django 中 M、V 和 C 各自的含义:
由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架 。在 MTV 开发模式中:
如果你熟悉其它的 MVC Web开发框架,比方说 Ruby on Rails,你可能会认为 Django 视图是控制器,而 Django 模板是视图。 很不幸,这是对 MVC 不同诠释所引起的错误认识。 在 Django 对 MVC 的诠释中,视图用来描述要展现给用户的数据;不是数据 如何展现 ,而且展现 哪些 数据。 相比之下,Ruby on Rails 及一些同类框架提倡控制器负责决定向用户展现哪些数据,而视图则仅决定 如何 展现数据,而不是展现 哪些 数据。
两种诠释中没有哪个更加正确一些。 重要的是要理解底层概念。
在视图中进行数据库查询的笨方法
正如前面详细介绍的那个在视图中输出 HTML 的笨方法(通过在视图里对文本直接硬编码HTML),在视图中也有笨方法可以从数据库中获取数据。 很简单: 用现有的任何 Python 类库执行一条 SQL 查询并对结果进行一些处理。
在本例的视图中,我们使用了 MySQLdb 类库(可以从 http://www.djangoproject.com/r/python-mysql/ 获得)来连接 MySQL 数据库,取回一些记录,将它们提供给模板以显示一个网页:
1 from django.shortcuts import render_to_response 2 import MySQLdb 3 4 def book_list(request): 5 db = MySQLdb.connect(user='root', db='data', passwd='123456t', host='localhost') 6 cursor = db.cursor() 7 cursor.execute('SELECT name FROM books ORDER BY name') 8 names = [row[0] for row in cursor.fetchall()] 9 db.close() 10 return render_to_response('book_list.html', {'names': names})
这个方法可用,但很快一些问题将出现在你面前:
正如你所期待的,Django数据库层正是致力于解决这些问题。 以下提前揭示了如何使用 Django 数据库 API 重写之前那个视图。
1 from django.shortcuts import render_to_response 2 from mysite.books.models import Book 3 4 def book_list(request): 5 books = Book.objects.order_by('name') 6 return render_to_response('book_list.html', {'books': books})
现在只是对其有个大致的认识,下次再深入理解此代码。