最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python使用Alembic遷移數(shù)據(jù)庫

 更新時間:2026年04月05日 09:18:34   作者:幻象黑兔  
本文主要介紹了Python使用Alembic遷移數(shù)據(jù)庫,它能幫助開發(fā)者有效地管理數(shù)據(jù)庫結(jié)構(gòu)變更,確保版本控制和可回滾特性,感興趣的可以了解一下

1. 什么是 Alembic,為什么需要它?

Alembic 是由 SQLAlchemy 的作者 Mike Bayer 編寫的數(shù)據(jù)庫遷移工具。你可以把它理解成「數(shù)據(jù)庫的 Git」——它跟蹤數(shù)據(jù)庫結(jié)構(gòu)(Schema)的變化,讓你可以在不同版本之間前進和后退。

沒有 Alembic 時的痛點

假設(shè)你在開發(fā)一個博客項目,一開始 users 表只有 idname,后來需要加一個 email 字段。你可能會:

  1. 手動登錄數(shù)據(jù)庫執(zhí)行 ALTER TABLE users ADD COLUMN email VARCHAR(255);
  2. 告訴團隊成員「記得去改一下數(shù)據(jù)庫」
  3. 生產(chǎn)環(huán)境上線時再手動執(zhí)行一遍

這種方式的問題顯而易見:容易遺漏、無法追蹤、無法回滾。

有了 Alembic 之后

  • 所有數(shù)據(jù)庫結(jié)構(gòu)的變更都以 遷移腳本 的形式保存在代碼倉庫中
  • 團隊成員只需執(zhí)行一條命令 alembic upgrade head 即可同步最新結(jié)構(gòu)
  • 可以隨時 回滾 到任意歷史版本
  • 支持自動檢測 SQLAlchemy Model 的變化,自動生成遷移腳本

2. 安裝與初始化

安裝

pip install alembic sqlalchemy

如果你使用 PostgreSQL:

pip install psycopg2-binary

初始化 Alembic 環(huán)境

在項目根目錄下執(zhí)行以下命令完成初始化:

alembic init alembic

執(zhí)行后,項目目錄結(jié)構(gòu)如下:

myproject/
├── alembic/
│   ├── env.py              # 核心配置腳本,每次運行遷移都會執(zhí)行
│   ├── README
│   ├── script.py.mako      # 遷移腳本的模板文件
│   └── versions/           # 存放所有遷移版本文件的目錄
│       └── (這里會生成遷移腳本)
├── alembic.ini             # Alembic 的主配置文件
└── app/
    └── models.py           # 你的 SQLAlchemy 模型

理解各個文件的作用

alembic.ini — 主配置文件,主要配置數(shù)據(jù)庫連接 URL:

[alembic]
# 遷移腳本存放位置
script_location = alembic

# 數(shù)據(jù)庫連接 URL
sqlalchemy.url = sqlalchemy.url = postgresql+psycopg2://username:password@db_ip:5432/db_name

# 省略其他...

env.py — 這是 Alembic 的核心運行腳本。每次你執(zhí)行任何 alembic 命令,這個文件都會被執(zhí)行。它負責:

  • 建立數(shù)據(jù)庫連接
  • 配置遷移上下文
  • 區(qū)分「在線模式」(直接執(zhí)行 SQL)和「離線模式」(生成 SQL 文件)

versions/ — 存放所有遷移文件。文件名格式類似 3512b954651e_add_users_table.py,使用部分 GUID 而非遞增整數(shù)來命名,這樣可以更好地支持分支合并。

3. 基本使用

1 創(chuàng)建你的第一個 Model

先創(chuàng)建一個簡單的 SQLAlchemy 模型文件:

# app/models.py
from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import declarative_base
import datetime

Base = declarative_base()

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50), nullable=False)
    email = Column(String(200), nullable=False, unique=True)
    created_at = Column(DateTime, default=datetime.datetime.utcnow)

2 將Model 與 Alembic關(guān)聯(lián)

修改 alembic/env.py,讓 Alembic 知道你的 Model 在哪里:

# alembic/env.py 中找到這行:
# target_metadata = None

# 替換為:
import sys
import os

from app.models import Base  # 導入你的 Base

target_metadata = Base.metadata  # 告訴 Alembic 用哪個 metadata 來檢測變化
# 或 target_metadata = [Base.metadata, ]

?? 新手常見錯誤:忘記把 target_metadata = None 改成你的 Base.metadata,導致自動生成的遷移腳本是空的。

3 創(chuàng)建第一個遷移腳本

alembic revision --autogenerate-m "create users table"

執(zhí)行后,alembic/versions/ 目錄下會生成類似這樣的文件:

# alembic/versions/673707e9f34b_create_users_table.py

"""create users table

Revision ID: 673707e9f34b
Revises: 
Create Date: 2026-03-20 08:57:19.170729

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

# 版本標識,Alembic 用這個來追蹤當前在哪個版本
revision: str = '673707e9f34b'
down_revision: Union[str, Sequence[str], None] = None # 前一個版本的 revision ID, None 表示這是第一個遷移
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=50), nullable=False),
    sa.Column('email', sa.String(length=200), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('email')
    )
    op.create_index(op.f('ix_users_id'), 'users', ['id'], unique=False)
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_users_id'), table_name='users')
    op.drop_table('users')
    # ### end Alembic commands ###

每個遷移腳本包含兩個函數(shù):

  • upgrade() — 應用變更(往新版本走)
  • downgrade() — 撤銷變更(往舊版本退)

4 執(zhí)行遷移(升級到最新版本)

alembic upgrade head

head 表示升級到最新版本。執(zhí)行后,Alembic 會:

  1. 連接數(shù)據(jù)庫
  2. 檢查 alembic_version 表(首次運行時自動創(chuàng)建),確認當前所處的版本
  3. 依次執(zhí)行所有尚未應用的遷移腳本中的 upgrade() 函數(shù)

如果你想升級到某個特定版本:

alembic upgrade 3512b954651e # Revision ID

或者升級 N 步:

alembic upgrade +2

5 回滾遷移

回滾到上一個版本:

alembic downgrade -1

回滾到某個特定版本:

alembic downgrade 3512b954651e # alembic downgrade 3512b954651e

回滾到最初狀態(tài)(撤銷所有遷移):

alembic downgrade base

4. 自動生成遷移腳本(autogenerate)

手動編寫遷移腳本很麻煩,Alembic 的殺手锏功能是 自動生成(autogenerate)

其工作原理是:將你的 SQLAlchemy Model 定義(目標狀態(tài))與數(shù)據(jù)庫中實際的表結(jié)構(gòu)(當前狀態(tài))進行比對,自動生成一個描述兩者「差異」的遷移腳本。

使用示例

假設(shè)你在 user.py 中新增了一個 phone 字段:

# app/models/User.py

from sqlalchemy import Column, Integer, String, DateTime
from sqlalchemy.orm import declarative_base
import datetime

Base = declarative_base()

class User(Base):
    __tablename__ = "users" # 命名約束,定義表名,建議添加

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50), nullable=False)
    email = Column(String(200), nullable=False, unique=True)
    phone = Column(String(20), nullable=False, unique=True) # 新增phone字段
    created_at = Column(DateTime, default=datetime.datetime.utcnow)

然后執(zhí)行自動生成命令:

alembic revision --autogenerate -m "add phone field to user table" 

Alembic 會自動生成:

# alembic/versions/7f29ab2b2004_add_phone_field_to_user_table.py
"""add phone field to user table

Revision ID: 7f29ab2b2004
Revises: 673707e9f34b
Create Date: 2026-03-20 09:12:51.346000

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision: str = '7f29ab2b2004'
down_revision: Union[str, Sequence[str], None] = '673707e9f34b'
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('users', sa.Column('phone', sa.String(length=20), nullable=False))
    op.create_unique_constraint(None, 'users', ['phone'])
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint(None, 'users', type_='unique')
    op.drop_column('users', 'phone')
    # ### end Alembic commands ###

最后執(zhí)行升級命令使變更生效:

alembic upgrade head

查看當前版本和歷史

查看當前數(shù)據(jù)庫所在的版本:

alembic current

輸出示例

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
7f29ab2b2004 (head)

查看所有遷移歷史:

alembic history

輸出示例:

673707e9f34b -> 7f29ab2b2004 (head), add phone field to user table
<base> -> 673707e9f34b, create users table

autogenerate 能檢測哪些變化?

默認支持檢測?

  • 新增 / 刪除表
  • 新增 / 刪除列
  • 列的 nullable 狀態(tài)變化
  • 基本索引變化
  • 顯式命名的唯一約束變化
  • 基本外鍵約束變化

無法檢測 ?

變化類型原因
表名重命名會被識別為「刪除舊表 + 新建新表」,需手動改成 rename 操作
列名重命名同上,會被識別為「刪除舊列 + 新增新列」,直接導致數(shù)據(jù)丟失
匿名約束沒有名字的約束無法被可靠追蹤
不原生支持 ENUM 的數(shù)據(jù)庫上的枚舉類型SQLite 等數(shù)據(jù)庫用 CHAR + CHECK 模擬枚舉,Alembic 無法從反射結(jié)果中判斷這是否是一個枚舉
存儲過程、函數(shù)、觸發(fā)器等超出 Alembic 的管理范圍

?? 自動生成的遷移腳本永遠不是 100% 完美的,每次生成后都必須人工審核! 這是官方文檔明確強調(diào)的原則,autogenerate 的目標是「輔助」而非「替代」人工判斷。

5.結(jié)合Fastapi + SQLModel使用

SQLModel是為FastApi設(shè)計的與數(shù)據(jù)庫交互的庫,基于 Python 類型注解,并由 Pydantic 和 SQLAlchemy 驅(qū)動。

1. 安裝依賴

pip install fastapi[standard] sqlmodel

2. 定義模型

# app/models/User.py
from sqlmodel import SQLModel, Field
from datetime import datetime, timezone

class UserBase(SQLModel):
    """
    用戶基礎(chǔ)模型
    公共字段基類,被 Create / Response 等 Schema 復用
    """
    name: str = Field(index=True, description="用戶名")
    email: str = Field(index=True, unique=True, description="用戶郵箱")
    created_at: datetime = Field(lambda: datetime.now(timezone.utc), description="創(chuàng)建時間")

class User(UserBase, table=True):
    """
    用戶模型
    映射數(shù)據(jù)庫表 users
    """

    __tablename__ = "users"
    id: int = Field(default=None, primary_key=True)

# request schema
class UserCreate(UserBase):
    """
    創(chuàng)建用戶的請求體
    """
    pass

# response schema
class UserRead(UserBase):
    """
    返回給前端的響應體
    """
    id: int

3. 修改遷移腳本模板文件

script.py.mako 是所有遷移腳本的模板文件。由于 SQLModel 生成的遷移腳本默認不會導入 sqlmodel 模塊,但生成的腳本內(nèi)容通常又依賴它,因此推薦在模板中統(tǒng)一添加這個導入,避免每次生成后都要手動修改。

# alembic/script.py.mako
# 添加 **import sqlmodel**

**"""${message}

Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
import sqlmodel # 新增代碼
${imports if imports else ""}

# revision identifiers, used by Alembic.
revision: str = ${repr(up_revision)}
down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)}
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}

def upgrade() -> None:
    """Upgrade schema."""
    ${upgrades if upgrades else "pass"}

def downgrade() -> None:
    """Downgrade schema."""
    ${downgrades if downgrades else "pass"}**

4. 配置 env.py

from app.models.User import User
target_metadata = [
    User.metadata,
]

# 省略其他

5.生成遷移腳本

alembic revision --autogenerate  -m "create users table"

生成的遷移腳本如下:

"""create users table

Revision ID: 54b2d338fcc9
Revises: 
Create Date: 2026-03-20 10:11:18.524007

"""
from typing import Sequence, Union

from alembic import op
import sqlalchemy as sa
import sqlmodel # 如果不修改mako文件,這里需要手動引入sqlmodel

# revision identifiers, used by Alembic.
revision: str = '54b2d338fcc9'
down_revision: Union[str, Sequence[str], None] = None
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users',
    sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
    sa.Column('email', sqlmodel.sql.sqltypes.AutoString(), nullable=False),
    sa.Column('created_at', sa.DateTime(), nullable=False),
    sa.Column('id', sa.Integer(), nullable=False),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_users_email'), 'users', ['email'], unique=True)
    op.create_index(op.f('ix_users_name'), 'users', ['name'], unique=False)
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_users_name'), table_name='users')
    op.drop_index(op.f('ix_users_email'), table_name='users')
    op.drop_table('users')
    # ### end Alembic commands ###

6. 多環(huán)境管理

實際項目中,通常需要分別管理本地開發(fā)、預發(fā)布(staging)和生產(chǎn)(production)三套環(huán)境的數(shù)據(jù)庫,每套環(huán)境都有各自獨立的連接配置和遷移歷史。Alembic 支持通過 -n 參數(shù)指定目標環(huán)境來實現(xiàn)這一需求。

1. 修改alembic.ini

[alembic]
script_location = alembic/local
sqlalchemy.url = postgresql+psycopg2://username:paasowrd@local_db_ip:5432/local_db_name

[staging]
script_location = alembic/staging
sqlalchemy.url = postgresql+psycopg2://username:paasowrd@staging_db_ip:5432/staging_db_name

[production]
script_location = alembic/production
sqlalchemy.url = postgresql+psycopg2://username:paasowrd@production_db_ip:5432/production_db_ip_name

[DEFAULT]
prepend_sys_path = .
version_path_separator = os
# 省略其他配置

2. 初始化alembic環(huán)境

alembic init alembic/local
alembic -n staging init alembic/staging
alembic -n production init alembic/production

生成的目錄結(jié)構(gòu)如下

your_project/
├── alembic/
│   ├── local/
│   │   └── versions/
│   ├── production/
│   │   └── versions/
│   └── staging/
│       └── versions/
├── app/
│   └── models/
└── alembic.ini

3. 針對不同環(huán)境執(zhí)行遷移

# local(默認環(huán)境,無需 -n 參數(shù))
alembic revision --autogenerate -m "add users table"
alembic upgrade head

# staging
alembic -n staging revision --autogenerate -m "add users table"
alembic -n staging upgrade head

# production 
alembic -n production revision --autogenerate -m "add users table"
alembic -n production upgrade head

7. 生產(chǎn)環(huán)境最佳實踐

1. 遷移前務必備份數(shù)據(jù)庫

在對生產(chǎn)數(shù)據(jù)庫執(zhí)行任何遷移之前,應當先完整備份,以防遷移失敗時可以快速恢復。

# 全量備份
pg_dump -U postgres -F c  -v -f test_db_$(date +%Y%m%d_%H%M%S).backup test_db

# 若需要恢復
psql -U postgres -c "CREATE DATABASE test_db_restore;"
pg_restore -U postgres -d test_db_restore -v --clean test_db_20260320_031055.backup

2. 生產(chǎn)環(huán)境的數(shù)據(jù)庫 URL 不應硬編碼在配置文件中

將數(shù)據(jù)庫連接地址明文寫入 alembic.ini 存在安全隱患,推薦改用 pydantic_settings 從環(huán)境變量中讀取。

第一步:刪除 alembic.ini 中的 sqlalchemy.url

# 刪除sqlalchemy.url
[production]
script_location = alembic/production

第二步:新增 pydantic 配置文件

# app/core/settings.py
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    DATABASE_URL: str

settings = Settings()

第三步:修改 production 的 env.py

# alembic/production/env.py

from app.core.settings import settings

# 使用環(huán)境變量里的databse url配置
config.set_main_option("sqlalchemy.url", settings.DATABASE_URL) 

第四步:設(shè)置環(huán)境變量后再執(zhí)行遷移命令

# 設(shè)置遷URL后再執(zhí)行遷移命令
export DATABASE_URL="你的DATABSE_URL" 
alembic -n production revision --autogenerate  -m "create users table"

8. 枚舉類型的正確處理方式

枚舉(Enum)字段的遷移處理是一個容易踩坑的地方,值得單獨說明。

為什么不推薦 PostgreSQL 原生 Enum?

Alembic 雖然支持 PostgreSQL 的原生 Enum 類型,但實際使用中存在以下問題:

  • PostgreSQL 原生枚舉類型只能追加值,不能刪除
  • 如果需要修改枚舉值,只能重建整個枚舉類型,操作繁瑣
  • Alembic 無法自動識別枚舉值的變化,需要完全手動處理遷移腳本
# app/models/User.py
from enum import Enum
from sqlmodel import SQLModel, Field
from datetime import datetime, timezone

class UserStatus(str, Enum):
    """用戶狀態(tài)枚舉"""
    ACTIVE = "active"
    BANNED = "banned"
    DELETED = "deleted"

class UserBase(SQLModel):
		# 省略其他
    status: UserStatus = Field(default=UserStatus.ACTIVE, description="用戶狀態(tài)") # 使用原生Enum,?不推薦

推薦方案:varchar+ CHECK 約束

使用 sa_column 將字段定義為 varchar 類型,并通過 CHECK 約束限制合法值范圍。這樣 Alembic 就能檢測到枚舉值的變化并自動生成遷移腳本。

# app/models/User.py
from sqlalchemy import Column, Enum as SaEnum

class UserBase(SQLModel):
    status: UserStatus | None = Field(
        default=None,
        description="用戶狀態(tài)",
        sa_column=Column(SaEnum(
                    UserStatus, 
                    name="user_status", 
                    create_constraint=True, 
                    native_enum=False, 
                    nullable=True
        ))
    )
    # 省略其他

生成的遷移腳本如下:

# alembic/production/versions/568f7d9f2553_change_status_field.py

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column(
        'users', 
        sa.Column(
            'status', 
            sa.Enum('ACTIVE', 'BANNED', 'DELETED', 
                name='user_status', 
                native_enum=False, 
                create_constraint=True
            ), 
            nullable=True
        )
    )
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('users', 'status')
    # ### end Alembic commands ###

查看 users 表的約束,可以看到 status 字段類型為 varchar,并關(guān)聯(lián)了名為 user_status 的 CHECK 約束。

這種方案最大的優(yōu)勢是:當你修改 UserStatus 枚舉時,Alembic 能夠自動識別變化并生成對應的遷移腳本。

場景一:新增枚舉值

# app/models/User.py

class UserStatus(str, Enum):
    """用戶狀態(tài)枚舉"""
    ACTIVE = "active"
    BANNED = "banned"
    DELETED = "deleted"
    IN_ACTIVE = "in_active" # 新增

自動生成的遷移腳本如下:

# alembic/production/versions/568f7d9f2553_change_status_field.py

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.alter_column('users', 'status',
               existing_type=sa.VARCHAR(length=7),
               type_=sa.Enum('ACTIVE', 'BANNED', 'DELETED', 'IN_ACTIVE', name='user_status', native_enum=False, create_constraint=True),
               existing_nullable=True)
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.alter_column('users', 'status',
               existing_type=sa.Enum('ACTIVE', 'BANNED', 'DELETED', 'IN_ACTIVE', name='user_status', native_enum=False, create_constraint=True),
               type_=sa.VARCHAR(length=7),
               existing_nullable=True)
    # ### end Alembic commands ###

注意:直接執(zhí)行上述腳本會報錯:

sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateObject) constraint "user_status" for relation "users" already exists

原因是 Alembic 在 alter_column 時會嘗試重新創(chuàng)建 CHECK 約束,但舊的約束還未刪除。需要手動在腳本中先刪除舊約束:

# alembic/production/versions/568f7d9f2553_change_status_field.py

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('user_status', 'users', type_='check') # 手動添加:先刪除舊約束
    op.alter_column('users', 'status',
               existing_type=sa.VARCHAR(length=7),
               type_=sa.Enum('ACTIVE', 'BANNED', 'DELETED', 'IN_ACTIVE', name='user_status', native_enum=False, create_constraint=True),
               existing_nullable=True)
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('user_status', 'users', type_='check') # # 手動添加:先刪除舊約束
    op.alter_column('users', 'status',
               existing_type=sa.Enum('ACTIVE', 'BANNED', 'DELETED', 'IN_ACTIVE', name='user_status', native_enum=False, create_constraint=True),
               type_=sa.VARCHAR(length=7),
               existing_nullable=True)
    # ### end Alembic commands ###

場景二:修改已有枚舉值

?? Alembic 只能檢測枚舉結(jié)構(gòu)的增刪變化(新增或刪除某個枚舉值),對于修改枚舉值本身(如將 BANNED 改為 DISABLED)則無法感知,需要完全手動編寫遷移腳本。

# app/models/User.py

class UserStatus(str, Enum):
    """用戶狀態(tài)枚舉"""
    ACTIVE = "active"
    DISABLED = "disabled" # 將BANNED修改為DISABLED
    DELETED = "deleted"
    IN_ACTIVE = "in_active"

對于這類情況,需要手動編寫遷移腳本,包括:先刪除舊約束、更新現(xiàn)有數(shù)據(jù)中的歷史枚舉值、再創(chuàng)建新約束:

# alembic/productionversions/0d46a300af09_change_status_banned_to_disabled.py

def upgrade() -> None:
    """Upgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('user_status', 'users', type_='check')
    op.execute("UPDATE users SET status = 'IN_ACTIVE' WHERE status = 'IS_ACTIVE'")
    op.execute("UPDATE users SET status = 'DISABLED' WHERE status = 'BANNED'")
    op.create_check_constraint(
        'user_status', 'users',
        "status IN ('ACTIVE', 'DISABLED', 'DELETED', 'IN_ACTIVE')"
    )
    # ### end Alembic commands ###

def downgrade() -> None:
    """Downgrade schema."""
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint('user_status', 'users', type_='check')
    op.execute("UPDATE users SET status = 'BANNED' WHERE status = 'DISABLED'")
    op.create_check_constraint(
        'user_status', 'users',
        "status IN ('ACTIVE', 'BANNED', 'DELETED', 'IN_ACTIVE')"
    )
    # ### end Alembic commands ###
```Alembic入門教程

到此這篇關(guān)于Python使用Alembic遷移數(shù)據(jù)庫的文章就介紹到這了,更多相關(guān)Python Alembic遷移數(shù)據(jù)庫內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 利用Matplotlib繪制折線圖、散點圖、柱狀圖、直方圖、餅圖的實例

    利用Matplotlib繪制折線圖、散點圖、柱狀圖、直方圖、餅圖的實例

    這篇文章主要介紹了利用Matplotlib繪制折線圖、散點圖、柱狀圖、直方圖、餅圖的實例代碼,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • python  創(chuàng)建一個保留重復值的列表的補碼

    python 創(chuàng)建一個保留重復值的列表的補碼

    這篇文章主要介紹了python 創(chuàng)建一個保留重復值的列表的補碼的相關(guān)資料,需要的朋友可以參考下
    2018-10-10
  • Python如何批量處理經(jīng)緯度數(shù)據(jù)并生成位置信息

    Python如何批量處理經(jīng)緯度數(shù)據(jù)并生成位置信息

    這篇文章主要介紹了Python如何批量處理經(jīng)緯度數(shù)據(jù)并生成位置信息問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Python獲取DLL和EXE文件版本號的方法

    Python獲取DLL和EXE文件版本號的方法

    這篇文章主要介紹了Python獲取DLL和EXE文件版本號的方法,實例分析了Python獲取系統(tǒng)文件信息的技巧,需要的朋友可以參考下
    2015-03-03
  • Python讀取mat(matlab數(shù)據(jù)文件)并實現(xiàn)畫圖

    Python讀取mat(matlab數(shù)據(jù)文件)并實現(xiàn)畫圖

    這篇文章主要介紹了Python讀取mat(matlab數(shù)據(jù)文件)并實現(xiàn)畫圖問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • python中函數(shù)的參數(shù)詳解

    python中函數(shù)的參數(shù)詳解

    本文詳細講解了python中函數(shù)的參數(shù),文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07
  • python使用protobufde的過程解析

    python使用protobufde的過程解析

    Google開源的一個序列化框架,類似于xml , json。最大的特點是基于 二進制,比傳統(tǒng)的xml表示同樣的內(nèi)容要短小很多。亦可定義一些可選字段,用于服務端與客戶端通信
    2021-08-08
  • python內(nèi)置函數(shù)之eval函數(shù)詳解

    python內(nèi)置函數(shù)之eval函數(shù)詳解

    這篇文章主要為大家介紹了python內(nèi)置函數(shù)之eval函數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-01-01
  • python函數(shù)局部變量用法實例分析

    python函數(shù)局部變量用法實例分析

    這篇文章主要介紹了python函數(shù)局部變量用法,較為詳細的分析了Python局部變量的原理與使用技巧,并對比分析了局部變量與global全局變量的用法區(qū)別,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-08-08
  • Pandas-DataFrame知識點匯總

    Pandas-DataFrame知識點匯總

    這篇文章主要介紹了Pandas-DataFrame知識點匯總,DataFrame是一種表格型數(shù)據(jù)結(jié)構(gòu),它含有一組有序的列,每列可以是不同的值,下面我們一起進入文章了解更多詳細內(nèi)容吧,需要的小伙伴也可以參考一下
    2022-03-03

最新評論

霞浦县| 嘉荫县| 上杭县| 历史| 和平区| 禹州市| 章丘市| 德钦县| 滦南县| 黄浦区| 峨眉山市| 桂林市| 东辽县| 宜春市| 咸丰县| 鹤岗市| 抚顺县| 辽宁省| 皮山县| 乌鲁木齐县| 阿勒泰市| 丰原市| 南京市| 高安市| 北宁市| 区。| 随州市| 南岸区| 屏山县| 涟水县| 科尔| 淅川县| 安福县| 山阳县| 林芝县| 黔西县| 永和县| 宜宾县| 葫芦岛市| 玉林市| 三明市|