Fork me on GitHub

新博客地址:voidy's blog

Python框架之Django学习笔记(九)

Posted on 2014-09-20 21:38  尛鱼  阅读(1173)  评论(2编辑  收藏  举报

模型

  之前,我们用 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 各自的含义:

  • M ,数据存取部分,由django数据库层处理,本章要讲述的内容。
  • V ,选择显示哪些数据要显示以及怎样显示的部分,由视图和模板处理。
  • C ,根据用户输入委派视图的部分,由 Django 框架根据 URLconf 设置,对给定 URL 调用适当的 Python 函数。

  由于 C 由框架自行处理,而 Django 里更关注的是模型(Model)、模板(Template)和视图(Views),Django 也被称为 MTV 框架 。在 MTV 开发模式中:

  • M 代表模型(Model),即数据存取层。 该层处理与数据相关的所有事务: 如何存取、如何验证有效性、包含哪些行为以及数据之间的关系等。
  • T 代表模板(Template),即表现层。 该层处理与表现相关的决定: 如何在页面或其他类型文档中进行显示。
  • V 代表视图(View),即业务逻辑层。 该层包含存取模型及调取恰当模板的相关逻辑。 你可以把它看作模型与模板之间的桥梁。

  如果你熟悉其它的 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 配置中。
  • 我们不得不重复同样的代码: 创建数据库连接、创建数据库游标、执行某个语句、然后关闭数据库。 理想情况下,我们所需要应该只是指定所需的结果。
  • 它把我们栓死在 MySQL 之上。 如果过段时间,我们要从 MySQL 换到 SQLServer,就不得不使用不同的数据库适配器,改变连接参数,根据 SQL 语句的类型可能还要修改SQL 。 理想情况下,应对所使用的数据库服务器进行抽象,这样一来只在一处修改即可变换数据库服务器。 (如果你正在建立一个开源的Django应用程序来尽可能让更多人使用的话,这个特性是非常适当的。)

  正如你所期待的,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})

  现在只是对其有个大致的认识,下次再深入理解此代码。