Flask-SQLAlchemy小写索引跳转功能,不支持SQLAlchemy反射[英] Flask-SQLAlchemy Lower Case Index - skipping functional, not supported by SQLAlchemy reflection

本文是小编为大家收集整理的关于Flask-SQLAlchemy小写索引跳转功能,不支持SQLAlchemy反射的处理方法,想解了Flask-SQLAlchemy小写索引跳转功能,不支持SQLAlchemy反射的问题怎么解决?Flask-SQLAlchemy小写索引跳转功能,不支持SQLAlchemy反射问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

首先.抱歉,如果已经回答了,但是我找不到任何答案.

我需要在烧瓶 - 塞拉尔奇米对象上定义小写索引.

我遇到的问题是我需要一个模型用户名和电子邮件字段才能存储小写,以便我可以使用User.query.filter(func.lower(username) == func.lower(username)).first()

检查它们

到目前为止,我一直通过将这些字段插入小写,但是在此特定实例中,我需要用户名来保留其定义的情况.

我认为我在正确的轨道上,但正在遇到我以前从未见过的问题.

class User(UserMixin, db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    # Indexes for username and email are defined below User
    # They are functional lowercase indexes
    username = db.Column(db.String(32))
    email = db.Column(db.String(255))
    password_hash = db.Column(db.String(255))

    ...

db.Index('ix_users_username', func.lower(User.username), unique=True)
db.Index('ix_users_email', func.lower(User.email), unique=True)

我看不到这个问题.我猜想func.lower()需要将索引与我可以通过其他搜索所能说明的分开定义.

现在,当我运行迁移时,问题出现了,我会得到以下错误:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'users'
.../lib/python3.4/site-packages/alembic/util/messaging.py:69: UserWarning: autogenerate skipping functional index ix_users_email; not supported by SQLAlchemy reflection
  warnings.warn(msg)
.../lib/python3.4/site-packages/alembic/util/messaging.py:69: UserWarning: autogenerate skipping functional index ix_users_username; not supported by SQLAlchemy reflection

我不是100%确定为什么反射不支持这一点.我期望我的迁移会像以前那样添加它们,但将其包裹在较低的情况下.

我对手动编写迁移并不不利(因为我认为这可能是可能的,而不是100%确定),但是有人可以指出为什么这不起作用吗?

预先感谢 乔

更新

我通过将以下行添加到迁移中解决了此问题.

op.create_index('ix_users_username', 'users', [sa.text('lower(username)')])
op.create_index('ix_users_email', 'users', [sa.text('lower(email)')])

推荐答案

您需要使用Alembic的execute方法手动添加UNIQUE INDEX.将类似的内容添加到您的迁移脚本中.

from alembic import op
# ...

def upgrade():
    # ...
    op.execute(
        """ CREATE UNIQUE INDEX users_normalized_username
            ON users
            (lower(username))
        """
    )

def downgrade():
    # ...
    op.execute("DROP INDEX users_normalized_username")

您也可以添加ColumnProperty,因此您可以访问username的归一化表示形式.

from sqlalchemy import Column, String, func, orm

class User(Base):
    __tablename__ = 'users'

    username = Column(String(32))
    normalized_username = orm.column_property(func.lower(username))

    # ...

这不会在数据库中创建额外的列,但是您可以查询和对其进行比较.

session.query(User).filter(User.normalized_username == func.lower(username)).first()

其他推荐答案

我找到了一个可以做到的黑客,在您的模型文件中,您不会添加新索引,但您会修改现有索引.然后运行数据库迁移,它应该能够为您生成炼金术python代码.然后,您只需要调整炼金术Python代码即可将其重命名为新的索引名称.并再次修改模型文件以添加您的新索引并将您在现有索引之前进行的修改恢复.

本文地址:https://www.itbaoku.cn/post/1763840.html