Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Amalan Terbaik untuk Alembic dan SQLAlchemy

Amalan Terbaik untuk Alembic dan SQLAlchemy

Mary-Kate Olsen
Mary-Kate Olsenasal
2024-11-01 10:20:30755semak imbas

Dalam artikel ini, saya akan membincangkan secara ringkas beberapa amalan terbaik yang membantu memastikan projek teratur, memudahkan penyelenggaraan pangkalan data dan mengelakkan perangkap biasa apabila bekerja dengan Alembic dan SQLAlchemy. Teknik-teknik ini telah menyelamatkan saya daripada masalah lebih daripada sekali. Inilah perkara yang akan kami bincangkan:

  1. Konvensyen Penamaan
  2. Isih Migrasi mengikut Tarikh
  3. Komen Jadual, Lajur dan Migrasi
  4. Pengendalian Data dalam Migrasi tanpa Model
  5. Ujian Migrasi (Ujian Tangga)
  6. Perkhidmatan untuk Menjalankan Migrasi
  7. Menggunakan Mixin untuk Model

1. Konvensyen Penamaan

SQLAlchemy membolehkan anda menyediakan konvensyen penamaan yang digunakan secara automatik pada semua jadual dan kekangan apabila menjana migrasi. Ini menjimatkan anda daripada menamakan indeks secara manual, kunci asing dan kekangan lain, yang menjadikan struktur pangkalan data boleh diramal dan konsisten.

Untuk menyediakan ini dalam projek baharu, tambahkan konvensyen pada kelas asas supaya Alembic akan menggunakan format penamaan yang diingini secara automatik. Berikut ialah contoh konvensyen yang berfungsi dengan baik dalam kebanyakan kes:

from sqlalchemy import MetaData
from sqlalchemy.orm import DeclarativeBase

convention = {
    'all_column_names': lambda constraint, table: '_'.join(
        [column.name for column in constraint.columns.values()]
    ),
    'ix': 'ix__%(table_name)s__%(all_column_names)s',
    'uq': 'uq__%(table_name)s__%(all_column_names)s',
    'ck': 'ck__%(table_name)s__%(constraint_name)s',
    'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s',
    'pk': 'pk__%(table_name)s',
}

class BaseModel(DeclarativeBase):
    metadata = MetaData(naming_convention=convention)

2. Menyusun Migrasi mengikut Tarikh

Nama fail migrasi alembic biasanya bermula dengan teg semakan, yang boleh menjadikan susunan migrasi dalam direktori kelihatan rawak. Kadangkala adalah berguna untuk memastikannya disusun mengikut kronologi.

Alembic membenarkan menyesuaikan templat nama fail migrasi dalam fail alembic.ini dengan tetapan file_template. Berikut ialah dua format penamaan yang mudah untuk memastikan migrasi teratur:

  1. Berdasarkan tarikh:
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
  1. Berdasarkan cap waktu Unix:
file_template = %%(epoch)d_%%(rev)s_%%(slug)s

Menggunakan cap masa tarikh atau Unix dalam nama fail memastikan migrasi teratur, menjadikan navigasi lebih mudah. Saya lebih suka menggunakan cap waktu Unix dan contoh akan diberikan dalam bahagian seterusnya.

3. Ulasan untuk Jadual dan Migrasi

Bagi mereka yang bekerja dalam pasukan, mengulas atribut ialah amalan yang baik. Dengan model SQLAlchemy, pertimbangkan untuk menambah ulasan terus pada lajur dan jadual dan bukannya bergantung pada docstrings. Dengan cara ini, ulasan tersedia dalam kod dan pangkalan data, menjadikannya lebih mudah bagi DBA atau penganalisis memahami tujuan jadual dan medan.

class Event(BaseModel):
    __table_args__ = {'comment': 'System (service) event'}

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        comment='Event ID - PK',
    )
    service_id: Mapped[int] = mapped_column(
        sa.Integer,
        sa.ForeignKey(
            f'{IntegrationServiceModel.__tablename__}.id',
            ondelete='CASCADE',
        ),
        nullable=False,
        comment='FK to integration service that owns the event',
    )
    name: Mapped[str] = mapped_column(
        sa.String(256), nullable=False, comment='Event name'
    )

Menambah ulasan pada migrasi juga berguna untuk menjadikannya lebih mudah ditemui dalam sistem fail. Komen boleh ditambah dengan -m apabila menjana migrasi. Komen akan muncul dalam docstring dan nama fail. Penamaan ini menjadikannya lebih mudah untuk mencari migrasi yang diperlukan.

from sqlalchemy import MetaData
from sqlalchemy.orm import DeclarativeBase

convention = {
    'all_column_names': lambda constraint, table: '_'.join(
        [column.name for column in constraint.columns.values()]
    ),
    'ix': 'ix__%(table_name)s__%(all_column_names)s',
    'uq': 'uq__%(table_name)s__%(all_column_names)s',
    'ck': 'ck__%(table_name)s__%(constraint_name)s',
    'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s',
    'pk': 'pk__%(table_name)s',
}

class BaseModel(DeclarativeBase):
    metadata = MetaData(naming_convention=convention)

4. Elakkan Menggunakan Model dalam Migrasi

Model sering digunakan untuk manipulasi data, seperti memindahkan data dari satu jadual ke jadual lain atau mengubah suai nilai lajur. Walau bagaimanapun, menggunakan model ORM dalam migrasi boleh membawa kepada isu jika model berubah selepas migrasi dibuat. Dalam kes sedemikian, migrasi berdasarkan model lama akan terputus apabila dilaksanakan, kerana skema pangkalan data mungkin tidak lagi sepadan dengan model semasa.

Migrasi hendaklah statik dan bebas daripada keadaan semasa model untuk memastikan pelaksanaan yang betul tanpa mengira perubahan kod. Di bawah ialah dua cara untuk mengelak daripada menggunakan model untuk manipulasi data.

  • Gunakan SQL mentah untuk manipulasi data:
file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s
  • Tentukan Jadual Secara Terus dalam Penghijrahan: Jika anda ingin menggunakan SQLAlchemy untuk manipulasi data, anda boleh menentukan jadual secara manual secara langsung dalam migrasi. Ini memastikan skema statik pada masa pelaksanaan migrasi dan tidak akan bergantung pada perubahan dalam model.
file_template = %%(epoch)d_%%(rev)s_%%(slug)s

5. Ujian Tangga untuk Ujian Migrasi

Ujian Stairway melibatkan menguji secara progresif peningkatan/turun taraf migrasi langkah demi langkah untuk memastikan keseluruhan rantaian migrasi berfungsi dengan betul. Ini memastikan setiap migrasi boleh berjaya mencipta pangkalan data baharu dari awal dan menurunkan taraf tanpa masalah. Menambah ujian ini pada CI sangat berharga untuk pasukan, menjimatkan masa dan kekecewaan.

Best Practices for Alembic and SQLAlchemy

Mengintegrasikan ujian ke dalam projek anda boleh dilakukan dengan mudah dan cepat. Anda boleh mencari contoh kod dalam repositori ini. Ia juga termasuk ujian migrasi berharga lain yang mungkin membantu.

6. Perkhidmatan Migrasi

Perkhidmatan berasingan untuk melakukan migrasi. Ini hanyalah satu cara untuk melaksanakan migrasi. Apabila membangun secara tempatan atau dalam persekitaran yang serupa dengan pembangunan, kaedah ini sesuai dengan baik. Saya ingin mengingatkan anda tentang ciri depende_on bersyarat, yang berkaitan di sini. Kami mengambil imej aplikasi dengan Alembic dan menjalankannya dalam bekas yang berasingan. Kami menambah pergantungan pada pangkalan data dengan syarat bahawa migrasi bermula hanya apabila pangkalan data bersedia untuk mengendalikan permintaan (service_healthy). Selain itu, bergantung_pada bersyarat (service_completed_successfully) boleh ditambahkan untuk aplikasi, memastikan ia bermula hanya selepas migrasi berjaya diselesaikan.

class Event(BaseModel):
    __table_args__ = {'comment': 'System (service) event'}

    id: Mapped[uuid.UUID] = mapped_column(
        UUID(as_uuid=True),
        primary_key=True,
        comment='Event ID - PK',
    )
    service_id: Mapped[int] = mapped_column(
        sa.Integer,
        sa.ForeignKey(
            f'{IntegrationServiceModel.__tablename__}.id',
            ondelete='CASCADE',
        ),
        nullable=False,
        comment='FK to integration service that owns the event',
    )
    name: Mapped[str] = mapped_column(
        sa.String(256), nullable=False, comment='Event name'
    )

Syarat depende_on memastikan migrasi dijalankan hanya selepas pangkalan data sedia sepenuhnya dan aplikasi bermula selepas migrasi selesai.

7. Mixin untuk Model

Walaupun ini mungkin perkara yang jelas, adalah penting untuk tidak mengabaikannya. Menggunakan mixin ialah cara mudah untuk mengelakkan pertindihan kod. Mixin ialah kelas yang mengandungi medan dan kaedah yang kerap digunakan, yang boleh disepadukan ke dalam mana-mana model yang diperlukan. Sebagai contoh, kita sering memerlukan medan create_at dan updated_at untuk menjejak masa penciptaan dan kemas kini rekod. Ia juga boleh berguna untuk menggunakan id berdasarkan UUID untuk menyeragamkan kunci utama. Semua ini boleh dikapsulkan dalam campuran.

from sqlalchemy import MetaData
from sqlalchemy.orm import DeclarativeBase

convention = {
    'all_column_names': lambda constraint, table: '_'.join(
        [column.name for column in constraint.columns.values()]
    ),
    'ix': 'ix__%(table_name)s__%(all_column_names)s',
    'uq': 'uq__%(table_name)s__%(all_column_names)s',
    'ck': 'ck__%(table_name)s__%(constraint_name)s',
    'fk': 'fk__%(table_name)s__%(all_column_names)s__%(referred_table_name)s',
    'pk': 'pk__%(table_name)s',
}

class BaseModel(DeclarativeBase):
    metadata = MetaData(naming_convention=convention)

Dengan menambahkan campuran ini, kami boleh memasukkan id UUID dan cap masa dalam mana-mana model jika diperlukan:

file_template = %%(year)d-%%(month).2d-%%(day).2d_%%(rev)s_%%(slug)s

Kesimpulan

Mengendalikan migrasi boleh menjadi mencabar, tetapi mengikuti amalan mudah ini membantu memastikan projek teratur dan terurus. Menamakan konvensyen, pengisihan tarikh, ulasan dan ujian telah menyelamatkan saya daripada huru-hara dan membantu mengelakkan kesilapan. Saya harap artikel ini terbukti membantu — jangan ragu untuk berkongsi petua penghijrahan anda sendiri dalam ulasan!

Atas ialah kandungan terperinci Amalan Terbaik untuk Alembic dan SQLAlchemy. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn