Ачааллж байна...
Өмнөх хичээлд Alembic-ийн орчин үүсгэж, хоосон өгөгдлийн санд books хүснэгт үүсгэх анхны migration-оо бичсэн. Тэр нь эхлэл байсан — гэвч migration-ий жинхэнэ сорилт эхний хүснэгт үүсгэхэд биш, хэрэглэгчдийн өгөгдлөөр дүүрсэн хүснэгтийг өөрчлөхөд ирдэг. Бүлэг 13-ын эхний хичээлийн Анхны жишээг санаарай: Номын сангийн API-д үнэлгээ (rating) нэмэх шийдвэр гарсан ч create_all юу ч хийгээгүй, програм column books.rating does not exist гэсэн алдаа өгсөн. Энэ хичээлд яг тэр өөрчлөлтийг зөв аргаар — migration-оор — эхнээс дуустал хийнэ.
Бид бүтэн мөчлөгийг туулна: migration бичих, ажиллуулахаас өмнө түүний SQL-ийг харах, хэрэгжүүлэх, өгөгдөл дээр шалгах, түүхийг харах, буцаах, дахин хэрэгжүүлэх, Python-ы загварыг migration-тай хамт шинэчлэх. Downgrade хийхэд өгөгдөлд юу тохиолдохыг шударгаар харна.
Хичээлийн хоёр дахь хагаст илүү нарийн асуудалтай нүүр тулна: өгөгдөлтэй хүснэгтэд NOT NULL багана нэмэх. Хоосон хүснэгтэд энэ нь энгийн, харин мөртэй хүснэгтэд энгийн migration бүтэлгүйтдэг. Бид түүнийг санаатайгаар бүтэлгүйтүүлж, Alembic-ийн transaction өгөгдлийн санг хэрхэн хамгаалдгийг харж, дараа нь мэргэжлийн хөгжүүлэгчдийн хэрэглэдэг гурван алхамт аюулгүй загвараар шийднэ.
Хорин салбарт хэрэглэгддэг бүртгэлийн маягтад шинэ багана нэмэх тушаалыг санаарай. Хэрэв шинэ багана "заавал бөглөх" нүд бол хуучин мөрүүдэд юу тохиолдох вэ? Мянган хуучин бичилтэд тэр нүд хоосон — гэвч журам "хоосон байж болохгүй" гэж байна. Тушаал гарсан өдрөөс бүх хуучин бичилт журам зөрчсөн болно. Ухаалаг тушаал гурван алхамтай: эхлээд нүдийг "сонголттой" гэж нэм; дараа нь бүх хуучин бичилтэд тохирох утгыг нөхөж бөглө; эцэст нь бүх нүд бөглөгдсөний дараа "заавал" болго. Энэ хичээлийн хоёр дахь хагас яг энэ тушаалыг бичнэ.
Migration өгөгдөлд хэрхэн нөлөөлөхийг харахын тулд books хүснэгтэд хэдэн мөр хэрэгтэй. alembic-practice хавтсанд seed_books.sql файл үүсгэнэ (VS Code, UTF-8):
sql
INSERT INTO books (title, year, copies)
VALUES
('Монголын нууц товчоо', 1240, 2),
('Clean Code', 2008, 4),
('Python Crash Course', 2015, 5);Энэ скрипт юу гэж хэлж байна вэ гэвэл: “books хүснэгтэд гурван ном нэм.” PowerShell-д (кирилл тохиргоотой, өмнөх хичээлийн цонхонд) ажиллуулна:
powershell
psql -U postgres -d library_mig -f seed_books.sqlХүснэгт одоо:
id | title | year | copies
----+----------------------+------+--------
1 | Монголын нууц товчоо | 1240 | 2
2 | Clean Code | 2008 | 4
3 | Python Crash Course | 2015 | 5Энэ бол бидний "жинхэнэ хэрэглэгчдийн өгөгдөл" — migration түүнийг алдах ёсгүй.
Алхам 1: migration үүсгэх
Виртуал орчин идэвхтэй, $env:DATABASE_URL нь library_mig руу заасан эсэхийг шалгаад:
powershell
alembic revision -m "add rating to books"Үр дүн:
Generating C:\Users\...\alembic-practice\alembic\versions\8c4d2e7f1a3b_add_rating_to_books.py ... doneӨмнөх хичээлийн нэгэн адил таны дугаар өөр байх — 8c4d2e7f1a3b-ийг өөрийн дугаараар орлуулан уншаарай. Шинэ файлын толгойг харъя:
python
"""add rating to books
Revision ID: 8c4d2e7f1a3b
Revises: 3f2a1b9c8d7e
Create Date: 2026-10-10 22:05:41.112233
"""
...
revision: str = '8c4d2e7f1a3b'
down_revision: Union[str, Sequence[str], None] = '3f2a1b9c8d7e'Энэ удаад “Revises” ба down_revision хоосон биш — эхний migration-ий дугаар. Alembic одоогийн head-ийг олж, шинэ migration-ийг түүний араас автоматаар холбосон. Гинж уртаслаа: create books table ← add rating to books.
Алхам 2: upgrade ба downgrade бичих
python
def upgrade() -> None:
"""Upgrade schema."""
op.add_column("books", sa.Column("rating", sa.Integer, nullable=True))
op.create_check_constraint(
"books_rating_check", "books", "rating BETWEEN 1 AND 5"
)
def downgrade() -> None:
"""Downgrade schema."""
op.drop_constraint("books_rating_check", "books", type_="check")
op.drop_column("books", "rating")upgrade() юу гэж хэлж байна вэ гэвэл: “books хүснэгтэд rating гэсэн хоосон байж болох бүхэл тоон багана нэм; дараа нь rating нь 1-ээс 5-ын хооронд байх ёстой гэсэн books_rating_check дүрэм тавь.” downgrade() нь: “books_rating_check дүрмийг устга; дараа нь rating баганыг устга.”
Хоёр шийдвэрийг тайлбарлая. Нэгдүгээрт, rating хоосон байж болно (nullable=True). Энэ нь Бүлэг 2-ын NULL-ийн утгатай яг тохирно: хуучин номнуудад хэн ч үнэлгээ өгөөгүй — "мэдэгдэхгүй." Тэдгээрт 0 эсвэл 3 бичих нь худал мэдээлэл болно. Хоёрдугаарт, CHECK-ийг тусдаа алхмаар, нэртэйгээр нэмсэн. Бүлэг 4-ийн хичээлд CHECK нь NULL-ийг нэвтрүүлдэг гэж сурсан — тэгэхээр хуучин мөрүүдийн NULL утгууд дүрмийг зөрчихгүй. downgrade() нь upgrade()-ийн яг эсрэг дарааллаар ажилладгийг анзаараарай: сүүлд нэмсэн дүрмийг эхэлж устгаж, дараа нь баганыг. Энэ нь Бүлэг 5-ийн "хүүхдийг эхэлж, эцэг эхийг дараа нь" дүрэмтэй ижил логик — дүрэм баганаас хамааралтай тул түүнээс өмнө явах ёстой. Дүрмийн нэр бол яг энэ мөчид хэрэгтэй: drop_constraint түүнийг нэрээр нь олдог.
Алхам 3: ажиллуулахаас өмнө SQL-ийг харах
Өмнөх хичээлийн --sql горимыг энэ удаад хүрээтэйгээр ашиглана — зөвхөн шинэ migration-ий SQL:
powershell
alembic upgrade 3f2a1b9c8d7e:head --sqlЭнэ тушаал юу гэж хэлж байна вэ гэвэл: “3f2a1b9c8d7e-ээс head хүртэлх upgrade-ийн SQL-ийг ажиллуулахгүйгээр хэвлэ.” Үр дүн (товчилсон):
sql
BEGIN;
-- Running upgrade 3f2a1b9c8d7e -> 8c4d2e7f1a3b
ALTER TABLE books ADD COLUMN rating INTEGER;
ALTER TABLE books ADD CONSTRAINT books_rating_check CHECK (rating BETWEEN 1 AND 5);
UPDATE alembic_version SET version_num='8c4d2e7f1a3b' WHERE alembic_version.version_num = '3f2a1b9c8d7e';
COMMIT;Энэ бол Бүлэг 4-ийн ALTER хичээлийн ALTER TABLE ... ADD COLUMN — одоо Python-оос бичигдсэн. Төгсгөлийн UPDATE нь alembic_version-ийг шинэ дугаар руу шилжүүлж байна — Бүлэг 3-ын UPDATE, WHERE-тэй, зөвхөн хуучин дугаартай мөрийг. Бүгд нэг transaction-д. Ажиллуулахаасаа өмнө SQL-ийг уншиж, "энэ бол миний хүссэн зүйл мөн үү" гэж асуух нь Бүлэг 3-ын "эхлээд SELECT" дадлын migration-ий хувилбар.
Алхам 4: хэрэгжүүлэх ба шалгах
powershell
alembic upgrade headINFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
INFO [alembic.runtime.migration] Running upgrade 3f2a1b9c8d7e -> 8c4d2e7f1a3b, add rating to booksЭнэ мөр юу гэж хэлж байна вэ гэвэл: “3f2a1b9c8d7e-ээс 8c4d2e7f1a3b руу upgrade ажиллуулж байна.” Өмнөх хичээлээс ялгаатай нь сумны зүүн тал хоосон биш — Alembic alembic_version-ээс одоогийн байдлыг уншиж, зөвхөн хэрэгжээгүй нэг migration-ийг ажиллуулсан. Эхний migration дахин ажиллаагүй.
psql-ээр өгөгдлийг шалгая:
sql
SELECT id, title, copies, rating FROM books ORDER BY id; id | title | copies | rating
----+----------------------+--------+--------
1 | Монголын нууц товчоо | 2 |
2 | Clean Code | 4 |
3 | Python Crash Course | 5 |
(3 rows)Гурван ном бүгд хэвээр, шинэ rating багана хоосон (psql NULL-ийг хоосон нүдээр харуулдаг). Өгөгдөл алдагдаагүй. Хэрэглэгчид үнэлгээ өгсөн гэж бодъё:
sql
UPDATE books SET rating = 5 WHERE id = 2;
UPDATE books SET rating = 4 WHERE id = 3;Дүрэм ажиллаж байгааг шалгая:
sql
UPDATE books SET rating = 7 WHERE id = 1;ERROR: new row for relation "books" violates check constraint "books_rating_check"
DETAIL: Failing row contains (1, Монголын нууц товчоо, 1240, 2, 7).Энэ мессеж юу гэж хэлж байна вэ гэвэл: “books-ийн шинэ мөр books_rating_check дүрмийг зөрчлөө.” Migration-ий тавьсан дүрэм хууль болж ажиллаж байна, мессеж бидний өгсөн нэрээр нь хэлж байна.
Алхам 5: түүх
powershell
alembic history3f2a1b9c8d7e -> 8c4d2e7f1a3b (head), add rating to books
<base> -> 3f2a1b9c8d7e, create books tableЭнэ хариу юу гэж хэлж байна вэ гэвэл: “migration-уудын гинж, шинээс хуучин руу: хамгийн сүүлийнх нь ‘add rating to books’, түүний өмнөх нь ‘create books table’, түүний өмнө эхлэл.” Бүлэг 13-ын эхний хичээлийн "гурван сарын дараа хэн нэгэн 'энэ багана хэзээ, яагаад нэмэгдсэн бэ' гэж асуувал хариулт хаана ч бичигдээгүй" гэсэн асуудал шийдэгдлээ: хариулт энд, мөн migration файл бүрийн огноо, тайлбарт. Git-ийн git log-тэй хослуулбал хэн, ямар commit-д нэмсэн нь ч тодорхой.
Жишээ 1: downgrade ба өгөгдлийн шударга үнэ
Migration-ий хойш чиглэлийг туршъя — гэхдээ энэ удаад хүснэгтэд үнэлгээнүүд бий. Өмнөх байдал:
id | title | rating
----+----------------------+--------
1 | Монголын нууц товчоо |
2 | Clean Code | 5
3 | Python Crash Course | 4powershell
alembic downgrade -1INFO [alembic.runtime.migration] Running downgrade 8c4d2e7f1a3b -> 3f2a1b9c8d7e, add rating to booksДараах байдал (SELECT * FROM books ORDER BY id;):
id | title | year | copies
----+----------------------+------+--------
1 | Монголын нууц товчоо | 1240 | 2
2 | Clean Code | 2008 | 4
3 | Python Crash Course | 2015 | 5Бүтэц эхний migration-ий байдалд буцсан — rating багана алга. Номнууд бүрэн бүтэн. Харин Clean Code-ийн 5 ба Python Crash Course-ийн 4 гэсэн үнэлгээнүүд бүрмөсөн алга болсон. Downgrade-ийн op.drop_column нь Бүлэг 4-ийн DROP COLUMN — багана ба түүний бүх утгыг устгадаг.
Одоо дахин upgrade:
powershell
alembic upgrade headХүснэгт:
id | title | rating
----+----------------------+--------
1 | Монголын нууц товчоо |
2 | Clean Code |
3 | Python Crash Course |rating багана, books_rating_check дүрэм буцаж ирсэн — гэвч үнэлгээнүүд биш. Энэ бол Бүлэг 13-ын эхний хичээлийн “downgrade нь бүтцийг буцаана, өгөгдлийг үргэлж биш” гэсэн анхааруулгын бодит харагдац. Migration-ий upgrade-downgrade-upgrade мөчлөгийг өөрийн компьютер дээр туршилтын өгөгдлөөр хийх нь хэвийн, тэр ч бүү хэл зөвлөгдөх дадал. Харин жинхэнэ хэрэглэгчдийн өгөгдөлтэй орчинд downgrade хийхээс өмнө — ялангуяа DROP агуулсан downgrade — заавал backup хий. Үүнийг Бүлэг 15-д хийнэ.
Жишээ 2: Python-ы загварыг хамт шинэчлэх
Migration зөвхөн өгөгдлийн санг өөрчилсөн. Python-ы код rating-ийн тухай одоохондоо мэдэхгүй. alembic-practice хавтсанд models.py:
python
from sqlmodel import Field, SQLModel
class Book(SQLModel, table=True):
__tablename__ = "books"
id: int | None = Field(default=None, primary_key=True)
title: str
year: int | None = None
copies: int = 1
rating: int | None = NoneМөн туршилтын скрипт read_books.py:
python
import os
from sqlmodel import Session, create_engine, select
from models import Book
engine = create_engine(os.environ["DATABASE_URL"])
with Session(engine) as session:
for book in session.exec(select(Book).order_by(Book.id)):
print(book.id, book.title, book.rating)Ажиллуулна:
1 Монголын нууц товчоо None
2 Clean Code None
3 Python Crash Course NoneЭнэ код юу хийж байна вэ гэвэл: "номнуудыг id-ийн дарааллаар уншиж, нэр ба үнэлгээг хэвлэ." Python-ы None нь PostgreSQL-ийн NULL. Бүлэг 13-ын эхний хичээлийн column books.rating does not exist алдаа энд гарсангүй, учир нь migration бүтцийг Python-ы загвартай нийцүүлсэн. Анхаарах нэг зүйл: энэ скриптэд create_all огт байхгүй. Migration хэрэглэж эхэлсэн төсөлд бүтцийг зөвхөн migration удирдана — create_all нь хоёр дахь "эзэн" болж, migration-уудын мэдэхгүй хүснэгт үүсгэж, Бүлэг 13-ын эхний хичээлийн зөрүүг буцааж авчирна.
Хамгийн чухал нь дараагийн алхам: models.py-ийн өөрчлөлт ба 8c4d2e7f1a3b_add_rating_to_books.py migration-ийг нэг commit-д хийнэ — git add models.py alembic/versions/ ба git commit -m "Add rating to books". Энэ commit-ийг татаж авсан хэн ч alembic upgrade head ажиллуулж, кодтой нь нийцсэн бүтэцтэй болно. Код ба бүтэц хамт аялна.
Жишээ 3: өгөгдөлтэй хүснэгтэд NOT NULL багана — бүтэлгүйтэл
Одоо хичээлийн хоёр дахь хагас. Номын сан ном бүрийн хэлийг заавал бүртгэхээр шийдлээ — language хоосон байж болохгүй. Шинэ migration:
powershell
alembic revision -m "add language to books"Үүссэн файлд (дугаар нь 5e9a1c3d7b2f гэж үзье) энгийн хувилбарыг бичье:
python
def upgrade() -> None:
"""Upgrade schema."""
op.add_column("books", sa.Column("language", sa.Text, nullable=False))
def downgrade() -> None:
"""Downgrade schema."""
op.drop_column("books", "language")upgrade() юу гэж хэлж байна вэ гэвэл: “books хүснэгтэд хоосон байж болохгүй language текстэн багана нэм.” Ажиллуулна:
powershell
alembic upgrade headTraceback-ийн төгсгөлд:
sqlalchemy.exc.IntegrityError: (psycopg.errors.NotNullViolation) column "language" of relation "books" contains null values
[SQL: ALTER TABLE books ADD COLUMN language TEXT NOT NULL]Энэ мессеж юу гэж хэлж байна вэ гэвэл (Бүлэг 11-ийн давхаргаар): “books relation-ий language багана хоосон утгууд агуулж байна” — мөн доор нь бүтэлгүйтсэн SQL. Зүйрлэлийн асуудал: шинэ багана нэмэгдэх мөчид гурван хуучин номын language нүд хоосон (NULL) байх ёстой, гэтэл NOT NULL түүнийг хориглож байна. Бүлэг 4-ийн ALTER хичээлийн SQLite-ийн Cannot add a NOT NULL column with default value NULL алдааны PostgreSQL хувилбар. Хоосон хүснэгтэд энэ migration амжилттай ажиллах байсан — тиймээс ийм алдаа ихэвчлэн хөгжүүлэгчийн хоосон өгөгдлийн сан дээр биш, жинхэнэ өгөгдөлтэй server дээр анх илэрдэг.
Одоо хамгийн чухал асуулт: өгөгдлийн сан ямар байдалд үлдсэн бэ?
powershell
alembic current8c4d2e7f1a3bHead биш — rating-ийн migration дээр зогссон. psql-ийн \d books нь language баганагүй. Migration transaction-д ажилласан тул алдаа гарахад бүх зүйл цуцлагдсан — өгөгдлийн сан хагас өөрчлөгдөөгүй, alembic_version шинэчлэгдээгүй. Энэ бол Бүлэг 12-ын бүхэл байдлын баталгаа ба өмнөх хичээлийн “Will assume transactional DDL” мөрийн бодит үнэ цэнэ. Бид migration файлыг засаад дахин ажиллуулахад л хангалттай — энэ migration хэрэгжээгүй тул засах нь зөв (Бүлэг 13-ын эхний хичээлийн "хэрэгжсэн migration-ийг бүү засварла" дүрэм зөвхөн хэрэгжсэнд хамаарна).
Жишээ 4: гурван алхамт аюулгүй загвар
Зүйрлэлийн ухаалаг тушаалыг migration болгон бичье. 5e9a1c3d7b2f_add_language_to_books.py-ийн upgrade()-ийг солино:
python
def upgrade() -> None:
"""Upgrade schema."""
op.add_column("books", sa.Column("language", sa.Text, nullable=True))
op.execute("UPDATE books SET language = 'Англи' WHERE language IS NULL")
op.execute("UPDATE books SET language = 'Монгол' WHERE id = 1")
op.alter_column("books", "language", nullable=False)upgrade() юу гэж хэлж байна вэ гэвэл: "алхам 1 — language-ийг хоосон байж болохоор нэм; алхам 2 — бүх хоосон language-ийг 'Англи' болгож, дараа нь 1-р номыг 'Монгол' болго; алхам 3 — language-ийг хоосон байж болохгүй болго." Шинэ хэрэгсэл хоёр. op.execute() нь ямар ч SQL-ийг migration дотор шууд ажиллуулдаг — энд Бүлэг 3-ын UPDATE. Ийм өгөгдөл өөрчилдөг migration-ийг data migration гэж нэрлэдэг. op.alter_column() нь байгаа баганын шинж чанарыг өөрчилдөг — Бүлэг 4-т SQLite-д байхгүй гэж харсан ALTER COLUMN-ийн PostgreSQL хувилбар; PostgreSQL дээр энэ нь ALTER TABLE books ALTER COLUMN language SET NOT NULL болно.
Бүх гурван алхам нэг migration, нэг transaction-д багтсан нь маш чухал: хэрэв хоёр дахь алхамд алдаа гарвал эхний алхам ч цуцлагдана. Энэ хичээлийн жишээнд UPDATE-ийн утгууд энгийн, гэвч бодит төсөлд нөхөх утга нь өөр хүснэгтээс уншигдаж, эсвэл нарийн дүрмээр тооцоологдож болно — тэр ажил бүхэлдээ migration-ий хэсэг болж, Git-д түүхтэйгээр хадгалагдана.
Ажиллуулна:
powershell
alembic upgrade headINFO [alembic.runtime.migration] Running upgrade 8c4d2e7f1a3b -> 5e9a1c3d7b2f, add language to booksХүснэгт:
id | title | rating | language
----+----------------------+--------+----------
1 | Монголын нууц товчоо | | Монгол
2 | Clean Code | | Англи
3 | Python Crash Course | | АнглиХуучин мөр бүр утгатай болж, дараа нь багана NOT NULL болсон. Шалгая:
sql
INSERT INTO books (title) VALUES ('Шинэ ном');ERROR: null value in column "language" of relation "books" violates not-null constraint
DETAIL: Failing row contains (4, Шинэ ном, null, 1, null, null).Шинэ мөр language-гүйгээр орохгүй — хууль хүчинтэй. Түүх:
powershell
alembic history8c4d2e7f1a3b -> 5e9a1c3d7b2f (head), add language to books
3f2a1b9c8d7e -> 8c4d2e7f1a3b, add rating to books
<base> -> 3f2a1b9c8d7e, create books tableГурван migration, гурван бүтцийн өөрчлөлт, бүгд түүхтэйгээ. Өөр нэг хувилбар бий гэдгийг шударгаар хэлье: sa.Column("language", sa.Text, nullable=False, server_default="Англи") гэж DEFAULT-тэйгээр нэмбэл PostgreSQL хуучин мөрүүдийг тэр утгаар автоматаар бөглөнө — нэг алхам. Энэ нь бүх хуучин мөрт ижил утга тохирох үед хамгийн энгийн. Гурван алхамт загвар нь хуучин мөрүүдэд өөр өөр утга хэрэгтэй үед (энд "Монголын нууц товчоо" — Монгол) зайлшгүй бөгөөд илүү ил тод.
Хэрэв сонирхож байвал language-ийн migration-д downgrade()-ийн хийх ёстой зүйлийг бодоод үзээрэй: зөвхөн op.drop_column хангалттай юу? Дараа нь alembic downgrade -1, alembic upgrade head-ийг дахин ажиллуулж, хэлний утгууд upgrade-ийн UPDATE-үүдээр дахин бөглөгдөхийг хараарай — rating-аас ялгаатай нь энэ багана дахин үүсэхэд утгагүй үлдэхгүй. Яагаад? Мөн models.py-д language: str талбар нэмж, read_books.py-ийг хэлийг хэвлэдэг болгоод, бүх өөрчлөлтийг нэг commit-д хийгээрэй. Эдгээр нь зөвхөн санал бөгөөд дараагийн хичээлүүд тэдгээрийг хийсэн гэж тооцохгүй.
Өгөгдөлтэй хүснэгтэд DEFAULT-гүй NOT NULL багана нэмэх. Жишээ 3-т харсанчлан column ... contains null values гарна. Шийдэл: DEFAULT өгөх, эсвэл гурван алхамт загвар. Хоосон хөгжүүлэгчийн өгөгдлийн сан дээр энэ алдаа гарахгүй тул migration-ийг өгөгдөлтэй орчинд туршиж үзэх нь чухал.
Constraint-ийн нэрийг буруу бичих. downgrade()-д op.drop_constraint("books_rating_chk", ...) гэж нэрийг өөрөөр бичвэл downgrade constraint "books_rating_chk" of relation "books" does not exist гэсэн алдаа өгнө — “books relation-ий books_rating_chk constraint байхгүй.” upgrade ба downgrade-д ижил нэрийг хэрэглэ — тиймээс constraint бүрт ил тод нэр өгөх нь чухал; нэргүй бол PostgreSQL-ийн автомат нэрийг таах шаардлагатай болно.
Хоёр хөгжүүлэгч зэрэг migration үүсгэх. Та ба багийн гишүүн хоёулаа 8c4d2e7f1a3b-ийн араас тус тусдаа migration үүсгэвэл гинж салаална. alembic upgrade head гэхэд Multiple head revisions are present for given argument 'head' гарна — “head аргументэд олон head хувилбар байна.” Энэ нь Git-ийн хоёр салаатай адил. Alembic-ийн alembic merge тушаал хоёр салааг нэгтгэх migration үүсгэдэг — бодит багийн ажилд энэ тохиолддог тул нэрийг нь мэдэж байх нь тустай.
Migration-ий дараа create_all ажиллуулсаар байх. Жишээ 2-т дурдсанчлан бүтцийг хоёр газраас удирдах нь зөрүү үүсгэдэг. Migration хэрэглэж эхэлсэн төслөөс create_all-ийг хас.
Загвар ба migration-ийг тусад нь commit хийх. Хэрэв models.py-д rating нэмсэн commit migration-гүй бол түүнийг татаж авсан хүн Бүлэг 13-ын эхний хичээлийн column books.rating does not exist алдааг авна. Хамт commit хий.
Энэ хичээлд та өгөгдөлтэй хүснэгтэд багана нэмэх бүтэн мөчлөгийг migration-оор хийлээ. alembic revision шинэ migration-ийг одоогийн head-ийн араас автоматаар холбодог; op.add_column ба нэртэй op.create_check_constraint-оор rating нэмж, downgrade-д тэдгээрийг эсрэг дарааллаар устгалаа. Хүрээтэй --sql нь ажиллуулахаас өмнө ALTER TABLE ба alembic_version-ийн UPDATE-ийг харуулсан; upgrade нь зөвхөн хэрэгжээгүй migration-ийг ажиллуулж, хуучин өгөгдлийг хадгалсан; alembic history бүтцийн түүхийг харуулсан. Downgrade бүтцийг буцаасан ч баганын өгөгдлийг (үнэлгээнүүдийг) бүрмөсөн устгасан. Python-ы загварыг migration-тай нэг commit-д шинэчилж, create_all-ийг хассан. Өгөгдөлтэй хүснэгтэд NOT NULL багана шууд нэмэх нь contains null values алдаа өгсөн ч Alembic-ийн transaction өгөгдлийн санг хөндөөгүй; гурван алхамт загвар — хоосон байж болохоор нэмэх, op.execute-ээр нөхөх, op.alter_column-оор NOT NULL болгох — нэг migration-д асуудлыг шийдсэн.
Ингээд Бүлэг 13 дууслаа. Та өгөгдлийн сангийн бүтцийг кодтой хамт, түүхтэйгээр, бүх орчинд ижил хэрэгжүүлэх мэргэжлийн аргыг эзэмшлээ. Дараагийн бүлэгт бид FastAPI сургалтын "орчуулагч" — ORM — руу буцаж, түүнийг гүнзгий харна. SQLModel-д хүснэгтүүдийн хоорондын FOREIGN KEY-ийг Python-ы объектуудын холбоос болгон илэрхийлэх, тэгээд ORM-ийн хамгийн алдартай нууц алдааг — N+1 асуудлыг — query-ний логоос өөрийн нүдээр олж, хэмжилтээр засна.
Бүртгэлтэй болсноор энэ сургалтын бүх хичээлд хандах эрх авна.