Django ORM 簡介

2021-12-31 Linux中國

學習怎麼去使用 Python 的 web 框架中的對象關係映射與你的資料庫交互,就像你使用 SQL 一樣。

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

Django 的一個強大的功能是它的對象關係映射Object-Relational Mapper(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,是 「雙下劃線double underscore」 的縮寫。僅有幾個非字母數字的字符可以被用於 Python 中的對象名字;下劃線是其中的一個。這些在 ORM 中被用於顯式分隔過濾關鍵字filter key name的各個部分。在底層,字符串用這些下劃線分割開,然後這些標記分開處理。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中國 榮譽推出

相關焦點

  • 探索Django ORM的極限
    幸運的是,目前有一個開放的推送請求(https://github.com/django/django/pull/8119  )來解決這個問題,所以在Django的未來版本中,很可能會支持這個功能。上面的兩個例子只是從資料庫中的另一個對象中選擇一個值,但是我們也可以使用聚合的結果運行更複雜的查詢。下面是如何聚合子查詢中匹配行的總和的例子:
  • django模型使用
    之前寫過一篇django的模型關係,今天騰出時間把上篇的兄弟篇補上,來學習下django orm, 利用django的模型可以很方便的對資料庫進行操作
  • 一篇文章帶你了解Django ORM操作(基礎篇)
    Django models代碼from django.db import modelsclass Author(models.Model): name前置導入import osimport djangoos.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_orm_demo.settings")django.setup()from web import models查詢所有(all)
  • 優化Django ORM查詢
    >>> from django.db import connection>>> Post.objects.all()>>> connection.queries[ { 'sql': 'SELECT "blogposts_post"."id", "blogposts_post"."
  • Django ORM的簡單總結
    version': 1,    'disable_existing_loggers': False,    'handlers': { 'console': { 'class': 'logging.StreamHandler',        },    },    'loggers': { 'django.db.backends
  • 為Django開發者介紹SQLAIchemy ORM
    英文原文:https://apirobot.me/posts/introduction-to-sqlalchemy-orm-for-django-developers譯者: Yang
  • 一篇文章帶你了解Django ORM操作(高端篇)
    代碼from django.db.models import Avg,Sumprice = models.Book.objects.all().aggregate(所有書總價格=Sum代碼from django.db.models import Countret = models.Book.objects.values("publish_id").annotate
  • python測試開發django-76.ORM查詢之Q查詢
    >select * from yoyo_card where card_user = 'YOYO' or 'yoyo';filter() 查詢,查詢或關係MyDjango>python manage.py shell>>> from yoyo.models import Card>>> from django.db.models
  • Django ORM源碼解析(一)
    import osimport sysif __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "OpsManage.settings") from django.core.management import execute_from_command_line
  • 如何輕鬆了解 Python 必學的 django 框架?
    本文基於 django 官方英文文檔梳理了一下自定義管理操作需要做的工作,方便快速了解自定義管理操作的實現過程。Admin actions 簡介admin actions 是一些在 admin 站點下拉列表中可以選擇執行的簡單函數,比如刪除一個對象操作。
  • python程式設計師嘔心瀝血整理 Django 優秀資源大全
    django-templated-email, star:291 - 一個 Django 模板,能很容易地發送模板型郵件,可以使用 django 模板,或事務型郵件提供商(如 mailchimp, silverpop 等)。django-yubin, star:22 - django-mailer2 + django-mailviews,及其它功能。
  • Django 模板語言基礎來啦
    示例:djangoMy first name is }. My last name is }.過濾器簡介過濾器可以對變量做一些操作,例如給變量賦值,改變變量的值等。示例:傳入`{'django': 'the web framework for perfecalist With deadline '}`上下文字典時,該模板呈現為:djangoThe Web Framework For Perfectionists With Deadlines傳入參數給過濾器
  • 向Django Admin添加圖表
    簡介Django為資料庫後臺管理提供了一個具有CRUD接口的開箱即用的功能性管理UI。這涵蓋了基本內容和用戶管理系統的大多數用例。擴展 django-adminDjango後臺管理應用程式由ModelAdmin類組成。這些表示後臺管理界面中模型的可視視圖。默認情況下,一個ModelAdmin類有5個默認視圖:當你想要查看一個特定的模型時,ChangeList視圖是默認的後臺管理視圖。
  • 深入理解Django時區及naive datetime object和aware datetime object的區別
    TIME_ZONE = 'Asia/Shanghai'>>> from datetime import datetime>>> datetime.now()datetime.datetime(2016, 12, 7, 12, 41, 22, 729326)>>> from django.utils
  • Django第二十八課
    這裡大概有兩種方法:一是繼承django的用戶模型;二是使用新的模型拓展關聯User(🌟🌟🌟🌟🌟)。1. 繼承Django的用戶模型我們之前使用的User是在django.contrib.auth.models中引用的,我們可以查看這部分源碼,分析這個User是如何創建的。
  • django模型 和 Django QuerySet API
    Django 模型(資料庫)資料庫相關的代碼一般寫在models.pydjango-admin.pystartproject learn_models # 新建一個項目cd learn_models # 進入到該項目的文件夾django-admin.py startapppeople # 新建一個 people 應用(app)
  • Django+Vue項目學習第一篇:django後臺搭建
    版本C:\Users\HanMK\Desktop>python -m django --version2.2.1cd 到一個你想放置你代碼的目錄,然後運行以下命令C:\Users\HanMK\Desktop>django-admin startproject mysite將會在當前目錄下創建一個
  • Django第十八課
    from django.shortcuts import renderfrom django.contrib.contenttypes.models import ContentTypefrom read_count.utils import get_seven_days_read_data, get_today_hot_data