PRF:20171124 An introduction to the Django ORM.md

@qhwdw
This commit is contained in:
wxy 2017-12-17 18:52:57 +08:00
parent 804b1ba2a9
commit b9f83c7c48

View File

@ -1,19 +1,19 @@
Django ORM 简介
============================================================
### 学习怎么去使用 Python 的 web 框架中的对象关系映射与你的数据库交互,就像你使用 SQL 一样。
> 学习怎么去使用 Python 的 web 框架中的对象关系映射与你的数据库交互,就像你使用 SQL 一样。
![Getting to know the Django ORM](https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/web-spider-frame-framework.png?itok=Rl2AG2Dc "Getting to know the Django ORM")
Image by : [Christian Holmér][10]. Modified by Opensource.com. [CC BY-SA 4.0][11]
你可能听说过 [Django][12],它是一个被称为“完美主义者的最后期限” 的 Python web 框架。它是一匹 [可爱的小矮马][13]。
Django 的其中一个强大的功能是它的对象关系映射ORM它允许你去和你的数据库交互,就像使用 SQL 一样。事实上Django 的 ORM 就是创建 SQL 去查询和维护数据库的一个 Python 的方法,并且在一个 Python 方法中获取结果。 我说 _就是_ 一种方法,但实际上,它是一项非常聪明的工程,它利用了 Python 中比较复杂的部分,使得开发过程更容易
Django 的一个强大的功能是它的<ruby>对象关系映射<rt>Object-Relational Mapper</rt></ruby>ORM它允许你就像使用 SQL 一样去和你的数据库交互。事实上Django 的 ORM 就是创建 SQL 去查询和操作数据库的一个 Python 式方式,并且获得 Python 风格的结果。 我说的_是_一种方式但实际上它是一种非常聪明的工程方法它利用了 Python 中一些很复杂的部分,而使得开发者更加轻松
在我们开始去了解 ORM 是怎么工作的之前,我们需要一个去操作的数据库。和任何一个关系型数据库一样,我们需要去定义一堆表和它们的关系(即,它们相互之间联系起来的方式)。让我们使用我们熟悉的东西。比如说,我们需要去建一个有博客文章和作者的博客。每个作者有一个名字。一位作者可以有很多的博客文章。一篇博客文章可以有很多的作者、标题、内容和发布日期。
在我们开始去了解 ORM 是怎么工作之前,我们需要一个可以操作的数据库。和任何一个关系型数据库一样,我们需要去定义一堆表和它们的关系(即,它们相互之间联系起来的方式)。让我们使用我们熟悉的东西。比如说,我们需要去建一个有博客文章和作者的博客。每个作者有一个名字。一位作者可以有很多的博客文章。一篇博客文章可以有很多的作者、标题、内容和发布日期。
在 Django-ville 中,这个文章和作者的概念可以被称为博客应用。在这个语境中,一个应用是一个自包含一系列描述我们的博客行为和功能的模型和视图。用正确的方式打包,以便于其它的 Django 项目可以使用我们的博客应用。在我们的项目中,博客正是其中的一个应用。比如,我们也可以有一个论坛应用。但是,我们仍然坚持我们的博客应用的原有范围。
在 Django 村里,这个文章和作者的概念可以被称为博客应用。在这个语境中,一个应用是一个自包含一系列描述我们的博客行为和功能的模型和视图的集合。用正确的方式打包,以便于其它的 Django 项目可以使用我们的博客应用。在我们的项目中,博客正是其中的一个应用。比如,我们也可以有一个论坛应用。但是,我们仍然坚持我们的博客应用的原有范围。
这是为这个教程事先准备的 `models.py`
@ -36,23 +36,11 @@ class Post(models.Model):
        return self.title
```
更多的 Python 资源
现在,看上去似乎有点令人恐惧,因此,我们把它分解来看。我们有两个模型:作者(`Author`)和文章(`Post`)。它们都有名字(`name`)或者标题(`title`)。文章有个放内容的大的文本字段,以及用于发布时间和日期的 `DateTimeField`。文章也有一个 `ManyToManyField`,它同时链接到文章和作者。
* [Python 是什么?][1]
大多数的教程都是从头开始的,但是,在实践中并不会发生这种情况。实际上,你会得到一堆已存在的代码,就像上面的 `model.py` 一样,而你必须去搞清楚它们是做什么的。
* [最好的 Python IDEs][2]
* [最好的 Python GUI 框架][3]
* [最新的 Python 内容][4]
* [更多的开发者资源][5]
现在,看上去似乎有点令人恐惧,因此,我们把它分解来看。我们有两个模型:作者和文章。它们都有名字或者标题。文章为内容设置一个大文本框,以及为发布的时间和日期设置一个 `DateTimeField`。文章也有一个 `ManyToManyField`,它同时链接到文章和作者。
大多数的教程都是从 scratch—but 开始的,但是,在实践中并不会发生这种情况。实际上,它会提供给你一堆已存在的代码,就像上面的 `model.py` 一样,而你必须去搞清楚它们是做什么的。
因此,现在你的任务是去进入到应用程序中去了解它。做到这一点有几种方法,你可以登入到 [Django admin][14],一个 Web 后端,它有全部列出的应用和操作它们的方法。我们先退出它,现在我们感兴趣的东西是 ORM。
因此,现在你的任务是去进入到应用程序中去了解它。做到这一点有几种方法,你可以登入到 [Django admin][14],这是一个 Web 后端,它会列出全部的应用和操作它们的方法。我们先退出它,现在我们感兴趣的东西是 ORM。
我们可以在 Django 项目的主目录中运行 `python manage.py shell` 去访问 ORM。
@ -74,13 +62,13 @@ Type "help", "copyright", "credits" or "license" for more information.
它导入了全部的博客模型,因此,我们可以玩我们的博客了。
首先,我们列出所有的作者
首先,我们列出所有的作者
```
>>> Author.objects.all()
```
我们将从这个命令取得结果,它是一个 `QuerySet`,它列出了所有我们的作者对象。它不会充满我们的整个控制台因为如果有很多查询结果Django 将自动截断输出结果。
我们将从这个命令取得结果,它是一个 `QuerySet`,它列出了我们所有的作者对象。它不会充满我们的整个控制台因为如果有很多查询结果Django 将自动截断输出结果。
```
>>> Author.objects.all()
@ -88,7 +76,7 @@ Type "help", "copyright", "credits" or "license" for more information.
 <Author: Jen Wike Huger>, '...(remaining elements truncated)...']
```
我们可以使用 `get` 代替 `all` 去检索单个作者。但是,我们需要一些更多的信息 `get` 一个单个记录。在关系型数据库中,表有一个主键,它唯一标识了表中的每个记录,但是,作者名并不唯一。许多人都 [重名][16],因此,它不是唯一约束的一个选择。解决这个问题的一个方法是使用一个序列1、2、3...或者一个通用唯一标识符UUID作为主键。但是因为它对人类并不可用,我们可以通过使用 `name` 来操作我们的作者对象。
我们可以使用 `get` 代替 `all` 去检索单个作者。但是,我们需要一些更多的信息才能 `get` 一个单个记录。在关系型数据库中,表有一个主键,它唯一标识了表中的每个记录,但是,作者名并不唯一。许多人都 [重名][16]因此它不是唯一约束的好选择。解决这个问题的一个方法是使用一个序列1、2、3 ……或者一个通用唯一标识符UUID作为主键。但是因为它对人类并不好用,我们可以通过使用 `name` 来操作我们的作者对象。
```
>>> Author.objects.get(name="VM (Vicky) Brasseur")
@ -105,7 +93,7 @@ u'VM (Vicky) Brasseur'
然后,很酷的事件发生了。通常在关系型数据库中,如果我们希望去展示其它表的信息,我们需要去写一个 `LEFT JOIN`,或者其它的表耦合函数,并确保它们之间有匹配的外键。而 Django 可以为我们做到这些。
在我们的模型中,由于作者写了很多的文章,因此,我们的作者对象可以检查它自己的文章。
在我们的模型中,由于作者写了很多的文章,因此,我们的作者对象可以检索他自己的文章。
```
>>> vmb.posts.all()
@ -114,8 +102,8 @@ QuerySet[<Post: "7 tips for nailing your job interview">,
 <Post: "Quit making these 10 common resume mistakes">,
 '...(remaining elements truncated)...']
```
We can manipulate `QuerySets` using normal pythonic list manipulations.
我们可以使用正常的 Python 式的列表操作方式来操作 `QuerySets`
```
>>> for post in vmb.posts.all():
@ -126,20 +114,18 @@ We can manipulate `QuerySets` using normal pythonic list manipulations.
Quit making these 10 common resume mistakes
```
去实现更复杂的查询,我们可以使用过滤得到我们想要的内容。这是非常微妙的。在 SQL 中,你可以有一些选项,比如,`like`、`contains`、和其它的过滤对象。在 ORM 中这些事情也可以做到。但是,是通过 _特别的_ 方式实现的:是通过使用一个隐式(而不是显式)定义的函数实现的。
要实现更复杂的查询,我们可以使用过滤得到我们想要的内容。这有点复杂。在 SQL 中,你可以有一些选项,比如,`like`、`contains` 和其它的过滤对象。在 ORM 中这些事情也可以做到。但是,是通过 _特别的_ 方式实现的:是通过使用一个隐式(而不是显式)定义的函数实现的。
如果在我的 Python 脚本中调用了一个函数 `do_thing()`,我期望在某个地方有一个匹配 `def do_thing`。这是一个显式的函数定义。然而,在 ORM 中,你可以调用一个 _不显式定义的_ 函数。之前,我们使用 `name` 去匹配一个名字。但是,如果我们想做一个子串搜索,我们可以使用 `name__contains`
如果在我的 Python 脚本中调用了一个函数 `do_thing()`,我期望在某个地方有一个匹配 `def do_thing`。这是一个显式的函数定义。然而,在 ORM 中,你可以调用一个 _不显式定义的_ 函数。之前,我们使用 `name` 去匹配一个名字。但是,如果我们想做一个子串搜索,我们可以使用 `name__contains`
```
>>> Author.objects.filter(name__contains="Vic")
QuerySet[<Author: VM (Vicky) Brasseur>, <Author: Victor Hugo">]
```
现在,关于双下划线(`__`)我有一个小小的提示。这些是 Python _特有的_。在 Python 的世界里,你可以看到如 `__main__` 或者 `__repr__`。这些有时被称为 `dunder methods`,是 “双下划线” 的缩写。这里仅有几个非字母数字字符可以被用于 Python 中的对象名字;下划线是其中的一个。这些在 ORM 中被用于不同的过滤关键字的显式分隔。在底层,字符串被这些下划线分割。并且这个标记是分开处理的。`name__contains` 被替换成 `attribute: name, filter: contains`。在其它编程语言中,你可以使用箭头代替,比如,在 PHP 中是 `name->contains`。不要被双下划线吓着你,正好相反,它们是 Python 的好帮手(并且如果你斜着看,你就会发现它看起来像一条小蛇,想去帮你写代码的小蟒蛇)。
现在,关于双下划线(`__`)我有一个小小的提示。这些是 Python _特有的_。在 Python 的世界里,你可以看到如 `__main__` 或者 `__repr__`。这些有时被称为 `dunder methods`,是 “<ruby>双下划线<rt>double underscore</rt></ruby>” 的缩写。仅有几个非字母数字字符可以被用于 Python 中的对象名字;下划线是其中的一个。这些在 ORM 中被用于显式分隔<ruby>过滤关键字<rt>filter key name</rt></ruby>的各个部分。在底层,字符串用这些下划线分割开,然后这些标记分开处理。`name__contains` 被替换成 `attribute: name, filter: contains`。在其它编程语言中,你可以使用箭头代替,比如,在 PHP 中是 `name->contains`。不要被双下划线吓着你,正好相反,它们是 Python 的好帮手(并且如果你斜着看,你就会发现它看起来像一条小蛇,想去帮你写代码的小蟒蛇)。
ORM 是非常强大并且是 Python 特有的。不过,在 Django 的管理网站上我提到过上面的内容。
### [django-admin.png][6]
ORM 是非常强大并且是 Python 特有的。不过,还记得我在上面提到过的 Django 的管理网站吗?
![Django Admin](https://opensource.com/sites/default/files/u128651/django-admin.png "Django Admin")
@ -147,13 +133,13 @@ Django 的其中一个非常精彩的用户可访问特性是它的管理界面
ORM有多强大
### [django-admin-author.png][7]
![Authors list in Django Admin](https://opensource.com/sites/default/files/u128651/django-admin-author.png "Authors list in Django Admin")
好吧给你一些代码去创建最初的模型Django 转到基于 web 的门户,它是非常强大的,它可以使用我们前面用过的同样的原生函数。默认情况下,这个管理门户只有基本的东西,但这只是在你的模型中添加一些定义去改变外观的问题。例如,在早期的这些 `__str__` 方法中,我们使用这些去定义作者对象应该有什么?(在这种情况中,比如,作者的名字),做了一些工作后,你可以创建一个界面,让它看起来像一个内容管理系统,以允许你的用户去编辑他们的内容。(例如,为一个标记为 “已发布” 的文章,增加一些输入框和过滤)。
好吧给你一些代码去创建最初的模型Django 就变成了一个基于 web 的门户,它是非常强大的,它可以使用我们前面用过的同样的原生函数。默认情况下,这个管理门户只有基本的东西,但这只是在你的模型中添加一些定义去改变外观的问题。例如,在早期的这些 `__str__` 方法中,我们使用这些去定义作者对象应该有什么?(在这种情况中,比如,作者的名字),做了一些工作后,你可以创建一个界面,让它看起来像一个内容管理系统,以允许你的用户去编辑他们的内容。(例如,为一个标记为 “已发布” 的文章,增加一些输入框和过滤)。
如果你想去了解更多内容,[Django 美女的教程][17] 中关于 [the ORM][18] 的节有详细的介绍。在 [Django project website][19] 上也有丰富的文档。
如果你想去了解更多内容,[Django 美女的教程][17] 中关于 [the ORM][18] 的节有详细的介绍。在 [Django project website][19] 上也有丰富的文档。
(题图  [Christian Holmér][10]Opensource.com 修改. [CC BY-SA 4.0][11]
--------------------------------------------------------------------------------
@ -165,9 +151,9 @@ Katie McLaughlin - Katie 在过去的这几年有许多不同的头衔,她以
via: https://opensource.com/article/17/11/django-orm
作者:[Katie McLaughlin Feed ][a]
作者:[Katie McLaughlin][a]
译者:[qhwdw](https://github.com/qhwdw)
校对:[校对者ID](https://github.com/校对者ID)
校对:[wxy](https://github.com/wxy)
本文由 [LCTT](https://github.com/LCTT/TranslateProject) 原创编译,[Linux中国](https://linux.cn/) 荣誉推出