本文轉載自 Leon 的網誌
之前寫過一篇〈初探 Orator ORM〉,有介紹了 Orator ORM 的基礎操作,而此篇文章就專門介紹 Orator ORM 的 seeding 機制,本篇的範例也都延續自〈初探 Orator ORM〉,還沒讀過的朋友請趕快手刀點擊閱讀。
Seeding
Seeding 用於在資料庫內建出一堆資料,這些資料可以是用於資料庫初始化的資料,例如郵遞區號,也可以是用於測試的假資料,而 Orator ORM 使用的是 Faker 套件當作假資料產生器。
Orator ORM 的 Seeding 操作
再次回顧一下在〈初探 Orator ORM〉文中的專案結構:
project1
├── app.db
├── oratordemo
│ ├── database.py
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.p
│ └── models
│ └── __init__.py
├── poetry.lock
└── pyproject.toml
分別有放 migration 腳本檔的 migrations/ 和放 model 腳本檔的 models/,理所當然的 seeding 腳本就會放在 seeds/ 裡面,因此產生過 seeding 腳本之後的目錄結構就會長這樣:
project1
├── app.db
├── oratordemo
│ ├── __init__.py
│ ├── database.py
│ ├── config
│ │ └── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models
│ │ └── __init__.py
│ └── seeds
│ └── __init__.py
├── poetry.lock
└── pyproject.toml
與 migrations/ 和 models/ 一樣,這個 seeds/ 不用手動建立,Orator ORM 會替我們代勞。
另一個新的 config/ 則是放 model factory 腳本的地方,後面會再提到。
建立 Seeding 腳本
(porject1) ~/project1/oratordemo> orator make:seed user_table_seeder
database_seeder created successfully.
user_table_seeder created successfully.
進去 seeds/ 看一下,注意到除了預期的 user_ 裡面只有一個空的 建立 oratordemo/ 這邊會帶入一個 Orator ORM 自行產生的 Faker 物件,而 Faker 的用法也頗直覺。Faker 可以產出的假資料有許多種類,可以閱讀 Faker 的文件了解。 有了 model factory,我們回到 seeder 寫向工廠下單的部份。 把 user_ 從上面可以看出 seeder 和 model factory 的分工,model factory 負責實際的生產邏輯,而 seeder 負責向 model factory 下訂數量。 若要執行特定的 seeder,執行這樣的命令: 會這麼落落長是有原因的,Orator ORM 在跑 seeder 內如果有 若要執行一連串的 seeder,則可以把要跑的 seeder 定義在 database_ 如果前面跑 seeder 的命令,把指定特定 seeder 的參數拿掉,按照約定它就會去跑這支 database_ 跑完可以去看一下資料庫,應該可以看到確實有 seeding 的資料在內。 Orator ORM 沿襲了 ActiveRecord 的約定大於配置的風格,因此和 Laravel 的 Eloquent ORM 也有著類似的使用體驗,雖然在 Python 的世界 SQLAlchemy 由於歷史因素還是有較高的使用率,但對新專案來說 Orator ORM 是一個可以被認真考慮的選項。 覺得這篇文章對您有幫助請幫我們一鍵三連,拍手、訂閱、分享,小小的鼓勵是支撐我們分享的原動力,感謝讀完本文的您,也歡迎留下意見與我們交流。from orator.seeds import Seeder
class UserTableSeeder(Seeder):
def run(self):
"""
Run the database seeds.
"""
pass
run()
函式,這個函式就是在跑 seeding 時會被呼叫的函式,函式內放的就是建立 User 資料的敘述,但架構上我們會把實際產生假資料的邏輯抽離,在這邊我們引入 model factory 的概念,顧名思義,model factory 就是實際產生假資料的「工廠」,而 xxx_定義 Model Factory
from orator.orm import Factory
from oratordemo.models.user import User
factory = Factory()
@factory.define(User)
def users_factory(faker):
return {
'name': faker.name(),
'age': faker.random_int(min=1, max=115),
'birthday': faker.date_of_birth(minimum_age=0, maximum_age=115).strftime('%Y-%m-%d')
}
呼叫 Model Factory
from orator.seeds import Seeder
from oratordemo.config.factories import factory
from oratordemo.models.user import User
class UserTableSeeder(Seeder):
factory = factory
def run(self):
"""
Run the database seeds.
"""
self.factory(User, 50).create()
執行 Seeder
(project1) ~/project1> env PYTHONPATH='/home/leon/project1' orator db:seed --config=oratordemo/database.py --path=oratordemo/seeds/ --seeder=user_table_seeder
Are you sure you want to seed the database?: (yes/no) [no] yes
Database seeded!
import
敘述會引發 ModuleNotFoundError
這個問題,因此必須多加一個環境變數讓 Python 能找到我們要 import 的模組。call()
敘述來加入要跑的 seeder 們:from orator.seeds import Seeder
from oratordemo.seeds.user_table_seeder import UserTableSeeder
class DatabaseSeeder(Seeder):
def run(self):
"""
Run the database seeds.
"""
self.call(UserTableSeeder)
(project1) ~/project1> env PYTHONPATH='/home/leon/project1' orator db:seed --config=oratordemo/database.py --path=oratordemo/seeds/
Are you sure you want to seed the database?: (yes/no) [no] yes
Seeded: UserTableSeeder
Database seeded!
結語