ormar 中的 Alembic 迁移不起作用(FastAPI)

Alembic migrations in ormar not working (FastAPI)

我想通过 Alembic 迁移,但有些东西不起作用。我不明白我到底做错了什么。

我的 alembic .env

from logging.config import fileConfig

from sqlalchemy import create_engine
from sqlalchemy import engine_from_config
from sqlalchemy import pool
from db import ORMAR_DATABASE_URL
from alembic import context
import sys, os

sys.path.append(os.getcwd())
config = context.config

fileConfig(config.config_file_name)

from db import Base
target_metadata = Base.metadata
URL = "postgresql://admin:admin@localhost/fa_naesmi"



def run_migrations_offline():


context.configure(
    url=URL,
    target_metadata=target_metadata,
    literal_binds=True,
    dialect_opts={"paramstyle": "named"},
    user_module_prefix='sa.'
)

with context.begin_transaction():
    context.run_migrations()


def run_migrations_online():
connectable = create_engine(URL)

with connectable.connect() as connection:
    context.configure(
        connection=connection,
        target_metadata=target_metadata,
        user_module_prefix='sa.'
    )

    with context.begin_transaction():
        context.run_migrations()


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

我的db.py文件:

import sqlalchemy
import databases
from sqlalchemy.ext.declarative import declarative_base
ORMAR_DATABASE_URL = "postgresql://admin:admin@localhost/fa_naesmi"

Base = declarative_base()
metadata = sqlalchemy.MetaData()
database = databases.Database(ORMAR_DATABASE_URL)
engine = sqlalchemy.create_engine(ORMAR_DATABASE_URL)

和我的 models.py:

import datetime
import ormar
from typing import Optional
from db import database, metadata, Base


class MainMeta(Base, ormar.ModelMeta):
    metadata = metadata
    database = database


class Category(Base, ormar.Model):
    class Meta(MainMeta):
        pass

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)

使用 alembic revision -m "first" 后,它不会迁移我的模型。

revision = '9176fb20d67a'
down_revision = '9159cff21eb5'
branch_labels = None
depends_on = None

def upgrade():
    pass


def downgrade():
    pass

我已经在控制台 alembic revision --autogenerate -m "razraz" 中写入,它创建了 alembic 数据库表,但迁移仍然无法正常工作。

错误是由于使用 sqlalchemy 中的 declarative_base() 引起的。

Sqlalchemy由两个主要部分组成:

  • ORM - 这是一个包含模型、关系、查询等的对象关系映射部分
  • core - 更 'raw' 和基本,通常它与 table 和列创建以及查询生成(连接、where 子句等)有关

ormar 中仅使用后者,您不能应用 ORM 部分的任何概念。事实上 ormar 有点(基于 asyncpydantic 简化)等同于 ORM 部分。

这意味着你不能继承自 Base <- 那是我提到的 orm 部分。

因此您的样本应该类似于以下代码片段:

蒸馏器.env

from logging.config import fileConfig
from sqlalchemy import create_engine

from db import ORMAR_DATABASE_URL
from models import metadata # adjust path if needed
from alembic import context
import sys, os

sys.path.append(os.getcwd())
config = context.config

fileConfig(config.config_file_name)

# note how it's 'raw' metadata not the one attached to Base as there is no Base
target_metadata = metadata
URL = ORMAR_DATABASE_URL


def run_migrations_offline():


context.configure(
    url=URL,
    target_metadata=target_metadata,
    literal_binds=True,
    dialect_opts={"paramstyle": "named"},
    user_module_prefix='sa.'
)

with context.begin_transaction():
    context.run_migrations()


def run_migrations_online():
connectable = create_engine(URL)

with connectable.connect() as connection:
    context.configure(
        connection=connection,
        target_metadata=target_metadata,
        user_module_prefix='sa.'
    )

    with context.begin_transaction():
        context.run_migrations()


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()

db.py 文件:

import sqlalchemy
import databases
ORMAR_DATABASE_URL = "postgresql://admin:admin@localhost/fa_naesmi"

# note lack of declarative_base
metadata = sqlalchemy.MetaData()
database = databases.Database(ORMAR_DATABASE_URL)
engine = sqlalchemy.create_engine(ORMAR_DATABASE_URL)

models.py:

import datetime
import ormar
from typing import Optional
from db import database, metadata


# you cannot subclass Base class thats ORM part
class MainMeta(ormar.ModelMeta):
    metadata = metadata
    database = database


class Category(ormar.Model):
    class Meta(MainMeta):
        pass

    id: int = ormar.Integer(primary_key=True)
    name: str = ormar.String(max_length=100)

免责声明:我是 ormar 的创建者 - 如果您有更多问题或遇到问题,请在此处告诉我。如果这解决了您的问题,请记住将答案标记为已接受。

谢谢!