python - Flask-SQLAlchemy 小写索引 - 跳过功能,SQLAlchemy 反射不支持

标签 python postgresql flask sqlalchemy alembic

首先。很抱歉,如果这个问题得到了回答,但我无法在任何地方找到答案。

我需要在 Flask-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,这样您就可以访问用户名 的规范化表示。

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 - Flask-SQLAlchemy 小写索引 - 跳过功能,SQLAlchemy 反射不支持,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42153301/

相关文章:

python - 使用 joblib.Memory 在 AWS S3 中缓存数据

python - 如何捕获在python中的对象上调用的任何方法?

postgresql - WSOD 即将打开 drupal 7 项目的第一页

database - 为什么循环中的 Entity Framework Core 调用会抛出 InvalidOperationException?

python - CSP 不接受内联脚本哈希或随机数

python - 如何在 Flask 中对 HTTP 摘要身份验证进行单元测试?

python - 极坐标 DataFrame 行之间的分割值

python 从 switch 输出中提取

postgresql - 为什么看不到我的模式大小

python - flask : "from app import app"?