Alembic 업그레이드 스크립트에서 삽입 및 업데이트를 어떻게 실행합니까?
Alembic 업그레이드 중에 데이터를 변경해야합니다.
현재 첫 번째 개정판에 '플레이어'테이블이 있습니다.
def upgrade():
op.create_table('player',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.Unicode(length=200), nullable=False),
sa.Column('position', sa.Unicode(length=200), nullable=True),
sa.Column('team', sa.Unicode(length=100), nullable=True)
sa.PrimaryKeyConstraint('id')
)
'팀'테이블을 소개하고 싶습니다. 두 번째 개정판을 만들었습니다.
def upgrade():
op.create_table('teams',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=80), nullable=False)
)
op.add_column('players', sa.Column('team_id', sa.Integer(), nullable=False))
두 번째 마이그레이션에서 다음 데이터도 추가하고 싶습니다.
팀 테이블 채우기 :
INSERT INTO teams (name) SELECT DISTINCT team FROM players;
players.team 이름에 따라 players.team_id를 업데이트하십시오.
UPDATE players AS p JOIN teams AS t SET p.team_id = t.id WHERE p.team = t.name;
업그레이드 스크립트 내에서 삽입 및 업데이트를 실행하려면 어떻게합니까?
당신이 요구하는 것은 Alembic 문서에서 가장 널리 퍼진 스키마 마이그레이션 과 반대로 데이터 마이그레이션 입니다.
이 답변은 모델을 정의하기 위해 선언적 (class-Mapper-Table 또는 core와 반대)을 사용하고 있다고 가정합니다. 이것을 다른 형태에 적용하는 것은 비교적 간단해야합니다.
Alembic은 몇 가지 기본 데이터 함수 op.bulk_insert()
및 op.execute()
. 작업이 상당히 적 으면 사용하십시오. 마이그레이션에 관계 또는 기타 복잡한 상호 작용이 필요한 경우 아래에 설명 된대로 모델 및 세션의 전체 기능을 사용하는 것을 선호합니다.
다음은 세션에서 데이터를 조작하는 데 사용할 선언적 모델을 설정하는 예제 마이그레이션 스크립트입니다. 요점은 다음과 같습니다.
- 필요한 열을 사용하여 필요한 기본 모델을 정의하십시오. 모든 열이 필요하지 않고 기본 키와 사용할 열만 필요합니다.
업그레이드 기능 내에서를 사용
op.get_bind()
하여 현재 연결을 얻고 세션을 만드십시오.- 또는
bind.execute()
SQLAlchemy의 하위 수준을 사용 하여 SQL 쿼리를 직접 작성합니다. 이것은 간단한 마이그레이션에 유용합니다.
- 또는
응용 프로그램에서 일반적으로 하듯이 모델과 세션을 사용합니다.
"""create teams table
Revision ID: 169ad57156f0
Revises: 29b4c2bfce6d
Create Date: 2014-06-25 09:00:06.784170
"""
revision = '169ad57156f0'
down_revision = '29b4c2bfce6d'
from alembic import op
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class Player(Base):
__tablename__ = 'players'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String, nullable=False)
team_name = sa.Column('team', sa.String, nullable=False)
team_id = sa.Column(sa.Integer, sa.ForeignKey('teams.id'), nullable=False)
team = orm.relationship('Team', backref='players')
class Team(Base):
__tablename__ = 'teams'
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String, nullable=False, unique=True)
def upgrade():
bind = op.get_bind()
session = orm.Session(bind=bind)
# create the teams table and the players.team_id column
Team.__table__.create(bind)
op.add_column('players', sa.Column('team_id', sa.ForeignKey('teams.id'), nullable=False)
# create teams for each team name
teams = {name: Team(name=name) for name in session.query(Player.team).distinct()}
session.add_all(teams.values())
# set player team based on team name
for player in session.query(Player):
player.team = teams[player.team_name]
session.commit()
# don't need team name now that team relationship is set
op.drop_column('players', 'team')
def downgrade():
bind = op.get_bind()
session = orm.Session(bind=bind)
# re-add the players.team column
op.add_column('players', sa.Column('team', sa.String, nullable=False)
# set players.team based on team relationship
for player in session.query(Player):
player.team_name = player.team.name
session.commit()
op.drop_column('players', 'team_id')
op.drop_table('teams')
코드의 모델 은 데이터베이스 의 현재 상태 를 나타내고 마이그레이션은 그 과정의 단계를 나타내 므로 마이그레이션은 별도의 모델을 정의합니다 . 데이터베이스는 해당 경로를 따라 어떤 상태에있을 수 있으므로 모델이 아직 데이터베이스와 동기화되지 않을 수 있습니다. 매우주의하지 않는 한 실제 모델을 직접 사용하면 누락 된 열, 유효하지 않은 데이터 등의 문제가 발생합니다. 마이그레이션에 사용할 열과 모델을 정확히 명시하는 것이 더 명확합니다.
다음 예제에서와 같이 직접 SQL을 사용할 수도 있습니다 ( Alembic Operation Reference ) 참조 :
from alembic import op
# revision identifiers, used by Alembic.
revision = '1ce7873ac4ced2'
down_revision = '1cea0ac4ced2'
branch_labels = None
depends_on = None
def upgrade():
# ### commands made by andrew ###
op.execute('UPDATE STOCK SET IN_STOCK = -1 WHERE IN_STOCK IS NULL')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
I recommend to use SqlAlchemy core statements using an ad-hoc table, as detailed in the official documentation, because it allows the use of agnostic SQL and pythonic writing and is also self-contained. SqlAlchemy Core is the best of both worlds for migration scripts.
Here is an example of the concept:
from sqlalchemy.sql import table, column
from sqlalchemy import String
from alembic import op
account = table('account',
column('name', String)
)
op.execute(
account.update().\\
where(account.c.name==op.inline_literal('account 1')).\\
values({'name':op.inline_literal('account 2')})
)
# If insert is required
from sqlalchemy.sql import insert
from sqlalchemy import orm
session = orm.Session(bind=bind)
bind = op.get_bind()
data = {
"name": "John",
}
ret = session.execute(insert(account).values(data))
# for use in other insert calls
account_id = ret.lastrowid
'code' 카테고리의 다른 글
패키지 이름을 알고 애플리케이션 시작 (0) | 2020.10.25 |
---|---|
인쇄 대화 상자가 닫힌 후 자동으로 창 닫기 (0) | 2020.10.25 |
정수 부동 소수점 자체가 1.f로 보장됩니까? (0) | 2020.10.24 |
분기 전략 (0) | 2020.10.24 |
태그 간 Git 로그 (0) | 2020.10.24 |