作者 | Katie Mclaughlin
譯者 | qhwdw
學習怎麼去使用 Python 的 web 框架中的物件關係對映與你的資料庫互動,就像你使用 SQL 一樣。
你可能聽說過 Django[1],它是一個被稱為“完美主義者的最後期限” 的 Python web 框架。它是一匹 可愛的小矮馬[2]。
Django 的一個強大的功能是它的物件關係對映(ORM),它允許你就像使用 SQL 一樣去和你的資料庫互動。事實上,Django 的 ORM 就是建立 SQL 去查詢和運算元據庫的一個 Python 式方式,並且獲得 Python 風格的結果。 我說的是一種方式,但實際上,它是一種非常聰明的工程方法,它利用了 Python 中一些很複雜的部分,而使得開發者更加輕鬆。
在我們開始去瞭解 ORM 是怎麼工作之前,我們需要一個可以操作的資料庫。和任何一個關係型資料庫一樣,我們需要去定義一堆表和它們的關係(即,它們相互之間聯絡起來的方式)。讓我們使用我們熟悉的東西。比如說,我們需要去建模一個有部落格文章和作者的部落格。每個作者有一個名字。一位作者可以有很多的部落格文章。一篇部落格文章可以有很多的作者、標題、內容和釋出日期。
在 Django 村裡,這個文章和作者的概念可以被稱為部落格應用。在這個語境中,一個應用是一個自包含一系列描述我們的部落格行為和功能的模型和檢視的集合。用正確的方式打包,以便於其它的 Django 專案可以使用我們的部落格應用。在我們的專案中,部落格正是其中的一個應用。比如,我們也可以有一個論壇應用。但是,我們仍然堅持我們的部落格應用的原有範圍。
這是為這個教程事先準備的 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
)。它們都有名字(name
)或者標題(title
)。文章有個放內容的大的文字欄位,以及用於釋出時間和日期的 DateTimeField
。文章也有一個 ManyToManyField
,它同時連結到文章和作者。
大多數的教程都是從頭開始的,但是,在實踐中並不會發生這種情況。實際上,你會得到一堆已存在的程式碼,就像上面的 model.py
一樣,而你必須去搞清楚它們是做什麼的。
因此,現在你的任務是去進入到應用程式中去瞭解它。做到這一點有幾種方法,你可以登入到 Django admin[3],這是一個 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
命令[4] 為我們做了很多設定,包括匯入我們的設定和配置 Django 環境。雖然我們啟動了 shell,但是,在我們匯入它之前,我們並不能訪問我們的部落格模型。
>>> from blog.models import *
它匯入了全部的部落格模型,因此,我們可以玩我們的部落格了。
首先,我們列出所有的作者:
>>> Author.objects.all()
我們將從這個命令取得結果,它是一個 QuerySet
,它列出了我們所有的作者物件。它不會充滿我們的整個控制檯,因為,如果有很多查詢結果,Django 將自動截斷輸出結果。
>>> Author.objects.all()
<QuerySet [<Author: VM (Vicky) Brasseur>, <Author: Rikki Endsley>,
<Author: Jen Wike Huger>, '...(remaining elements truncated)...']
我們可以使用 get
代替 all
去檢索單個作者。但是,我們需要一些更多的資訊才能 get
一個單個記錄。在關係型資料庫中,表有一個主鍵,它唯一標識了表中的每個記錄,但是,作者名並不唯一。許多人都 重名[5],因此,它不是唯一約束的好選擇。解決這個問題的一個方法是使用一個序列(1、2、3 ……)或者一個通用唯一識別符號(UUID)作為主鍵。但是,因為它對人類並不好用,我們可以透過使用 name
來操作我們的作者物件。
>>> Author.objects.get(name="VM (Vicky) Brasseur")
<Author: VM (Vicky) Brasseur>
到現在為止,我們已經有了一個我們可以互動的物件,而不是一個 QuerySet
串列。我們現在可以與這個 Python 物件進行互動了,使用任意一個表列做為屬性去檢視物件。
>>> vmb = Author.objects.get(name="VM (Vicky) Brasseur")
>>> vmb.name
u'VM (Vicky) Brasseur'
然後,很酷的事件發生了。通常在關係型資料庫中,如果我們希望去展示其它表的資訊,我們需要去寫一個 LEFT JOIN
,或者其它的表耦合函式,並確保它們之間有匹配的外來鍵。而 Django 可以為我們做到這些。
在我們的模型中,由於作者寫了很多的文章,因此,我們的作者物件可以檢索他自己的文章。
>>> 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)...']
我們可以使用正常的 Python 式的串列操作方式來操作 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">]
現在,關於雙下劃線(__
)我有一個小小的提示。這些是 Python 特有的。在 Python 的世界裡,你可以看到如 __main__
或者 __repr__
。這些有時被稱為 dunder methods
,是 “雙下劃線” 的縮寫。僅有幾個非字母數字的字元可以被用於 Python 中的物件名字;下劃線是其中的一個。這些在 ORM 中被用於顯式分隔過濾關鍵字的各個部分。在底層,字串用這些下劃線分割開,然後這些標記分開處理。name__contains
被替換成 attribute: name, filter: contains
。在其它程式語言中,你可以使用箭頭代替,比如,在 PHP 中是 name->contains
。不要被雙下劃線嚇著你,正好相反,它們是 Python 的好幫手(並且如果你斜著看,你就會發現它看起來像一條小蛇,想去幫你寫程式碼的小蟒蛇)。
ORM 是非常強大並且是 Python 特有的。不過,還記得我在上面提到過的 Django 的管理網站嗎?
Django Admin
Django 的其中一個非常精彩的使用者可訪問特性是它的管理介面,如果你定義你的模型,你將看到一個非常好用的基於 web 的編輯門戶,而且它是免費的。
ORM,有多強大?
Authors list in Django Admin
好吧!給你一些程式碼去建立最初的模型,Django 就變成了一個基於 web 的門戶,它是非常強大的,它可以使用我們前面用過的同樣的原生函式。預設情況下,這個管理門戶只有基本的東西,但這隻是在你的模型中新增一些定義去改變外觀的問題。例如,在早期的這些 __str__
方法中,我們使用這些去定義作者物件應該有什麼?(在這種情況中,比如,作者的名字),做了一些工作後,你可以建立一個介面,讓它看起來像一個內容管理系統,以允許你的使用者去編輯他們的內容。(例如,為一個標記為 “已釋出” 的文章,增加一些輸入框和過濾)。
如果你想去瞭解更多內容,Django 美女的教程[6] 中關於 the ORM[7] 的節有詳細的介紹。在 Django project website[8] 上也有豐富的檔案。
(題圖 Christian Holmér[9],Opensource.com 修改. CC BY-SA 4.0[10])
作者簡介:
Katie McLaughlin - Katie 在過去的這幾年有許多不同的頭銜,她以前是使用多種語言的一位軟體開發人員,多種作業系統的系統管理員,和多個不同話題的演講者。當她不改變 “世界” 的時候,她也去享受烹飪、掛毯藝術,和去研究各種應用程式棧怎麼去處理 emoji。
via: https://opensource.com/article/17/11/django-orm
作者:Katie McLaughlin[12] 譯者:qhwdw 校對:wxy
本文由 LCTT 原創編譯,Linux中國 榮譽推出