上一篇以遊戲為例說明OOP開發方式,這次則以OOP開發資料庫應用程式。
Python有許多資料庫程式開發套件,其中Django、SQLAlchemy最為盛行,Django是一網頁架構套件,兼具資料庫存取模組,而SQLAlchemy則只聚焦在資料庫存取,可搭配其他網頁架構套件開發,例如Flask、FastAPI。
關聯式資料庫的存取方式為SQL語言,程式設計師須額外學習SQL,因此,有人提出ORM(Object Relational Mapping)技術,以類別(Class)對應資料表(Table),藉由操作物件的方式自動生成並執行SQL,對資料庫進行新增/更正/刪除/查詢(CRUD)動作,優點包括:
缺點包括:
以Django為例,使用ORM步驟如下:
先安裝Django套件,指令如下:
pip install django -U
範例1. Django最簡程式,程式目錄為mysite。
django-admin startproject mysite
cd mysite
python manage.py runserver
測試:開啟瀏覽器,輸入 http://localhost:8000/ 。
執行結果:
範例2. 延續範例1,建立模型及資料表。
python manage.py migrate
python manage.py startapp polls
INSTALLED_APPS = [
"polls.apps.PollsConfig",
"django.contrib.admin",
from django.db import models
# 問題
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
# 答案選項
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
python manage.py makemigrations polls
Migrations for 'polls':
polls\migrations\0001_initial.py
+ Create model Question
+ Create model Choice
python manage.py sqlmigrate polls 0001
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_text" varchar(200) NOT NULL, "pub_date" datetime NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" bigint NOT NULL REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED);
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;
python manage.py migrate
目前只有空白資料表,沒有資料,我們可以利用指令對資料庫進行新增/更正/刪除/查詢(CRUD),當然,正常是應該使用網頁,不過本文是介紹ORM,就先省略了。
範例3. 利用Django shell操作資料庫。
python manage.py shell
from polls.models import Choice, Question
Question.objects.all()
<QuerySet []>
from django.utils import timezone
q = Question(question_text="What's new president?", pub_date=timezone.now())
q.save()
q.id
執行結果:得到新增問題資料的id=1,再查看資料,確實有一筆資料。
但時間是格林威治時區,可修改mysite\settings.py的TIME_ZONE為Asia/Taipei及USE_TZ = False,再重新執行python manage.py shell。
修改問題。
q = Question.objects.first()
q.pub_date=timezone.now()
q.save()
執行結果:得到正確的時間。
刪除問題。
q.delete()
執行結果:再使用 Question.objects.all()查詢,已無該筆資料。
可設定篩選資料查詢。
Question.objects.filter(id=6) # 查id=6,可能傳回多筆(list)
Question.objects.frist() # 傳回第一筆
Question.objects.get(pk=6) # 傳回主鍵(primary key)=6的那一筆
c1 = Choice(question = q, choice_text = '川普', votes = 1)
c1.save()
c2 = Choice(question = q, choice_text = '賀錦麗', votes = 2)
c2.save()
讀者可以自GitHub複製src\13\mysite資料夾。
python manage.py runserver
http://localhost:8000/
python manage.py makemigrations
python manage.py migrate
以上就是ORM的操作方式,完全以OOP精神開發資料庫應用程式,從上一篇的遊戲開發及本篇,可以看到如何從分析、設計到程式撰寫連貫的脈絡。
Django的操作指令雖然繁瑣,與C# Entity Framework、Rust套件...等都是相似的作法,熟悉Migration Plan有助於ORM觀念的理解,且在佈署至測試及上線環境上也較方便,只要依照測試步驟3,就可以一次建立好所有資料表。
下一篇會討論資料庫設計(Schema design),並完成網頁設計。
本系列的程式碼會統一放在GitHub,本篇的程式放在src/13資料夾,歡迎讀者下載測試,如有錯誤或疏漏,請不吝指正。