Linux中國

Django ORM 簡介

你可能聽說過 Django,它是一個被稱為「完美主義者的最後期限」 的 Python web 框架。它是一匹 可愛的小矮馬

Django 的一個強大的功能是它的 對象關係映射 Object-Relational Mapper ORM),它允許你就像使用 SQL 一樣去和你的資料庫交互。事實上,DjangoORM 就是創建 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,這是一個 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,但是,在我們導入它之前,我們並不能訪問我們的博客模型。

>>> from blog.models import *

它導入了全部的博客模型,因此,我們可以玩我們的博客了。

首先,我們列出所有的作者:

>>> Author.objects.all()

我們將從這個命令取得結果,它是一個 QuerySet,它列出了我們所有的作者對象。它不會充滿我們的整個控制台,因為,如果有很多查詢結果,Django 將自動截斷輸出結果。

>>> Author.objects.all()
<QuerySet [<Author: VM (Vicky) Brasseur>, <Author: Rikki Endsley>,
 <Author: Jen Wike Huger>, &apos;...(remaining elements truncated)...&apos;]

我們可以使用 get 代替 all 去檢索單個作者。但是,我們需要一些更多的信息才能 get 一個單個記錄。在關係型資料庫中,表有一個主鍵,它唯一標識了表中的每個記錄,但是,作者名並不唯一。許多人都 重名,因此,它不是唯一約束的好選擇。解決這個問題的一個方法是使用一個序列(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&apos;VM (Vicky) Brasseur&apos;

然後,很酷的事件發生了。通常在關係型資料庫中,如果我們希望去展示其它表的信息,我們需要去寫一個 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">,
 &apos;...(remaining elements truncated)...&apos;]

我們可以使用正常的 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 中,你可以有一些選項,比如,likecontains 和其它的過濾對象。在 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,是 「 雙下劃線 double underscore 」 的縮寫。僅有幾個非字母數字的字元可以被用於 Python 中的對象名字;下劃線是其中的一個。這些在 ORM 中被用於顯式分隔 過濾關鍵字 filter key name 的各個部分。在底層,字元串用這些下劃線分割開,然後這些標記分開處理。name__contains 被替換成 attribute: name, filter: contains。在其它編程語言中,你可以使用箭頭代替,比如,在 PHP 中是 name->contains。不要被雙下劃線嚇著你,正好相反,它們是 Python 的好幫手(並且如果你斜著看,你就會發現它看起來像一條小蛇,想去幫你寫代碼的小蟒蛇)。

ORM 是非常強大並且是 Python 特有的。不過,還記得我在上面提到過的 Django 的管理網站嗎?

![Django Admin](/data/attachment/album/201712/17/185202ge3wx17hek2n1idi.png "Django Admin")

Django 的其中一個非常精彩的用戶可訪問特性是它的管理界面,如果你定義你的模型,你將看到一個非常好用的基於 web 的編輯門戶,而且它是免費的。

ORM,有多強大?

![Authors list in Django Admin](/data/attachment/album/201712/17/185202b8wpwl683uhuzlwt.png "Authors list in Django Admin")

好吧!給你一些代碼去創建最初的模型,Django 就變成了一個基於 web 的門戶,它是非常強大的,它可以使用我們前面用過的同樣的原生函數。默認情況下,這個管理門戶只有基本的東西,但這只是在你的模型中添加一些定義去改變外觀的問題。例如,在早期的這些 __str__ 方法中,我們使用這些去定義作者對象應該有什麼?(在這種情況中,比如,作者的名字),做了一些工作後,你可以創建一個界面,讓它看起來像一個內容管理系統,以允許你的用戶去編輯他們的內容。(例如,為一個標記為 「已發布」 的文章,增加一些輸入框和過濾)。

如果你想去了解更多內容,Django 美女的教程 中關於 the ORM 的節有詳細的介紹。在 Django project website 上也有豐富的文檔。

(題圖 Christian Holmér,Opensource.com 修改. CC BY-SA 4.0

作者簡介:

Katie McLaughlin - Katie 在過去的這幾年有許多不同的頭銜,她以前是使用多種語言的一位軟體開發人員,多種操作系統的系統管理員,和多個不同話題的演講者。當她不改變 「世界」 的時候,她也去享受烹飪、掛毯藝術,和去研究各種應用程序棧怎麼去處理 emoji。

via: https://opensource.com/article/17/11/django-orm

作者:Katie McLaughlin 譯者:qhwdw 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出


本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive

對這篇文章感覺如何?

太棒了
0
不錯
0
愛死了
0
不太好
0
感覺很糟
0
雨落清風。心向陽

    You may also like

    Leave a reply

    您的電子郵箱地址不會被公開。 必填項已用 * 標註

    此站點使用Akismet來減少垃圾評論。了解我們如何處理您的評論數據

    More in:Linux中國