您可能听说过 Django,这个 Python Web 框架是为“追求完美但有截止日期的人”而设计的。它就是那个带有可爱小马的框架。
Django 最强大的功能之一是其对象关系映射器 (ORM),它使您能够像使用 SQL 一样与数据库进行交互。实际上,Django 的 ORM 只是创建 SQL 以查询和操作数据库并以 Pythonic 方式获取结果的一种 Python 式方法。好吧,我说只是一种方法,但它实际上是非常聪明的工程设计,它利用 Python 中一些更复杂的部分来让开发人员的生活更轻松。
在我们开始研究 ORM 的工作原理之前,我们需要一个数据库来操作。与任何关系数据库一样,我们需要定义一堆表及其关系(即,它们彼此关联的方式)。让我们使用一些熟悉的东西。例如,假设我们要建模一个博客,该博客具有博客文章和作者。作者有名字。一位作者可以有多篇博客文章。一篇博客文章可以有多位作者,并且具有标题、内容和发布日期。
在 Django 的世界中,帖子和作者的概念可以称为我们的 Blog 应用程序。在这种情况下,应用程序是一组独立的模型和视图,它们描述了我们博客的行为和功能。以正确的方式打包,许多 Django 项目都可以使用我们的 Blog 应用程序。在我们的项目中,Blog 可能只是一个应用程序。例如,我们可能还有一个 Forum 应用程序。但是我们将坚持 Blog 应用程序的原始范围。
这是一个为此教程准备的 models.py
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
published_date = models.DateTimeField(blank=True, null=True)
author = models.ManyToManyField(Author, related_name="posts")
def __str__(self):
return self.title
现在这看起来可能有点吓人,所以让我们分解一下。我们有两个模型:Author 和 Post。每个模型都有一个名称或标题。Post 有一个用于内容的大文本字段和一个用于发布日期和时间的 DateTimeField
。Post 还有一个 ManyToManyField
,它将帖子和作者链接在一起。
大多数教程都从头开始——但这在实践中不会发生。实际上,您将获得一堆像上面的 model.py
这样的现有代码,并且您必须弄清楚所有这些代码的含义。
因此,您现在的任务是进入应用程序并四处看看。有几种方法可以做到这一点。您可以登录 Django 管理后台,这是一个基于 Web 的后端,其中列出了所有应用程序以及操作它们的方法。我们稍后会回到这一点;在这里我们对 ORM 感兴趣。
我们可以通过从 Django 项目的主目录运行 python manage.py shell
来访问 ORM。
/srv/web/django/ $ python manage.py shell
Python 3.6.3 (default, Nov 9 2017, 15:58:30)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
这将把我们带入交互式控制台。shell
命令为我们做了很多设置,包括导入我们的设置和配置 Django 环境。虽然我们已经启动了 shell,但在导入 Blog 模型之前,我们无法访问它。
>>> from blog.models import *
这将导入所有博客模型,以便我们可以使用我们的博客文章和作者。
首先,让我们获取所有作者的列表。
>>> Author.objects.all()
我们从这个命令得到的是结果的 QuerySet
,其中列出了我们所有的 Author 对象。我们也不会填满整个控制台,因为如果有大量结果,Django 会自动截断打印的结果。
>>> Author.objects.all()
<QuerySet [<Author: VM (Vicky) Brasseur>, <Author: Rikki Endsley>,
<Author: Jen Wike Huger>, '...(remaining elements truncated)...']
我们可以使用 get
而不是 all
来选择单个作者。但是我们需要更多信息才能 get
单个记录。在关系数据库中,表有一个主键字段,该字段为表中的每个记录都有一个唯一标识符;但是,作者姓名不是唯一的。很多人 同名同姓,所以这不是一个好的唯一约束。解决此问题的一种方法是将序列 (1, 2, 3...) 或通用唯一标识符 (UUID) 作为主键。但是由于这些对于人类来说不太好用,我们可以通过使用 name
来操作我们的 Author 对象。
>>> Author.objects.get(name="VM (Vicky) Brasseur")
<Author: VM (Vicky) Brasseur>
这一次,我们有一个可以与之交互的单个对象,而不是 QuerySet
列表。我们可以以 Pythonic 方式与此对象交互,使用任何表列作为属性来查看对象。
>>> vmb = Author.objects.get(name="VM (Vicky) Brasseur")
>>> vmb.name
u'VM (Vicky) Brasseur'
这就是很酷的事情发生的地方。通常在关系数据库中,如果我们想显示其他表的信息,我们需要编写 LEFT JOIN
或其他表耦合函数,以确保我们的外键在表之间匹配。Django 为我们处理了这一点。
在我们的模型中,作者撰写了许多帖子,因此我们的 Author 对象可以检查作者撰写了哪些帖子。
>>> vmb.posts.all()
QuerySet[<Post: "7 tips for nailing your job interview">,
<Post: "5 tips for getting the biggest bang for your cover letter buck">,
<Post: "Quit making these 10 common resume mistakes">,
'...(remaining elements truncated)...']
我们可以使用普通的 Pythonic 列表操作来操作 QuerySets
。
>>> for post in vmb.posts.all():
... print(post.title)
...
7 tips for nailing your job interview
5 tips for getting the biggest bang for your cover letter buck
Quit making these 10 common resume mistakes
为了进行更复杂的查询,我们可以使用过滤器而不是获取所有内容。这里变得棘手。在 SQL 中,您有诸如 like
、contains
和其他过滤对象之类的选项。您也可以在 ORM 中执行所有这些操作,但它有一种特殊的方式来执行它们:通过使用隐式(而不是显式)定义的函数。
如果我在我的 Python 脚本中调用一个函数 do_thing()
,我希望在某处会有一个匹配的 def do_thing
。这是一个显式的函数定义。但是,在 ORM 中,您可以调用一个未显式定义的函数。之前,我们使用 name
来匹配名称。但是,如果我们想进行子字符串搜索,我们可以使用 name__contains
。
>>> Author.objects.filter(name__contains="Vic")
QuerySet[<Author: VM (Vicky) Brasseur>, <Author: Victor Hugo">]
现在,关于双下划线 (__
) 的一个小提示。这些非常 Pythonic。您可能在 Python 世界的旅程中见过 __main__
或 __repr__
。这些有时被称为 dunder methods
,是“double underscore”的缩写。在 Python 中,只有少数非字母数字字符可以用于对象名称;下划线就是其中之一。这些在 ORM 中用作过滤器键名称的不同部分的显式分隔符。在底层,字符串被这些下划线分割,并且令牌被单独处理。name__contains
变为 attribute: name, filter: contains
。在其他编程语言中,您可以使用箭头代替,例如 PHP 中的 name->contains
。不要让双下划线吓到你,它们只是 Pythonic 助手!(如果您眯起眼睛,您可能会说它们看起来像小蛇,想要帮助您编写代码的小蟒蛇。)
ORM 非常强大且非常 Pythonic。但是我上面提到的 Django 管理后台 呢?

opensource.com
Django 最出色的用户可访问性功能之一是其管理界面。如果您定义了模型,您将免费获得一个漂亮的基于 Web 的编辑门户。
是什么驱动了这个功能?ORM。

opensource.com
没错!给定用于创建原始模型的代码,Django 将其变成了一个基于 Web 的门户,该门户使用我们之前使用的相同原始函数提供支持。默认情况下,管理后台是基本的,但这只是在您的模型中添加更多定义来更改管理后台外观的问题。例如,早期的那些 __str__
方法?我们使用它们来定义 Author 对象的外观(在本例中,仅是作者姓名)。通过一些工作,您可以创建一个感觉像完整内容管理系统的界面,该界面允许您的用户轻松编辑自己的内容(例如,添加用于标记帖子“已发布”的字段和过滤器)。
如果您想了解更多信息,关于 ORM 的 Django Girls 教程 部分有详细的演练。Django 项目网站上也有大量文档。
3 条评论