Những gì bạn đang yêu cầu là di chuyển dữ liệu , trái ngược với di chuyển giản đồ phổ biến nhất trong tài liệu Alembic.
Câu trả lời này giả sử bạn đang sử dụng khai báo (trái ngược với class-Mapper-Table hoặc core) để xác định các mô hình của mình. Nó sẽ tương đối đơn giản để điều chỉnh điều này với các hình thức khác.
Lưu ý rằng Alembic cung cấp một số chức năng dữ liệu cơ bản: op.bulk_insert()
và op.execute()
. Nếu các hoạt động khá tối thiểu, hãy sử dụng chúng. Nếu quá trình di chuyển yêu cầu các mối quan hệ hoặc các tương tác phức tạp khác, tôi muốn sử dụng toàn bộ sức mạnh của các mô hình và phiên như được mô tả bên dưới.
Sau đây là một ví dụ về tập lệnh di chuyển thiết lập một số mô hình khai báo sẽ được sử dụng để thao tác dữ liệu trong một phiên. Các điểm chính là:
Xác định các mô hình cơ bản bạn cần, với các cột bạn sẽ cần. Bạn không cần mọi cột, chỉ cần khóa chính và những cột bạn sẽ sử dụng.
Trong chức năng nâng cấp, sử dụng op.get_bind()
để lấy kết nối hiện tại và thực hiện một phiên với nó.
- Hoặc sử dụng
bind.execute()
để sử dụng SQLAlchemy cấp thấp hơn để viết các truy vấn SQL trực tiếp. Điều này rất hữu ích cho việc di chuyển đơn giản.
Sử dụng các mô hình và phiên như bạn thường làm trong ứng dụng của mình.
"""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')
Quá trình di chuyển xác định các mô hình riêng biệt vì các mô hình trong mã của bạn đại diện cho trạng thái hiện tại của cơ sở dữ liệu, trong khi quá trình di chuyển đại diện cho các bước trong quá trình thực hiện . Cơ sở dữ liệu của bạn có thể ở bất kỳ trạng thái nào dọc theo đường dẫn đó, vì vậy các mô hình có thể chưa đồng bộ hóa với cơ sở dữ liệu. Trừ khi bạn rất cẩn thận, việc sử dụng trực tiếp các mô hình thực sẽ gây ra vấn đề với các cột bị thiếu, dữ liệu không hợp lệ, v.v. Rõ ràng hơn là bạn phải trình bày rõ ràng chính xác những cột và mô hình nào bạn sẽ sử dụng trong quá trình di chuyển.
op.execute
vàoupgrade()
, có cách nào để cung cấp mẫu mặc định được sử dụng bằngalembic revision
lệnh (nội dung mặc định cho.py
tệp được tạo ) không?