不区分大小写的烧瓶 -SQLAlchemy 查询

我使用 Flask-SQLAlchemy 从用户数据库中进行查询;

user = models.User.query.filter_by(username="ganye").first()

会回来的

<User u'ganye'>

做什么

user = models.User.query.filter_by(username="GANYE").first()

报税表

None

我想知道是否有办法以不区分大小写的方式查询数据库,以便第二个示例仍然返回

<User u'ganye'>
76787 次浏览

你可以在你的过滤器中使用 lower或者 upper函数:

from sqlalchemy import func
user = models.User.query.filter(func.lower(User.username) == func.lower("GaNyE")).first()

另一种选择是使用 ilike而不是 like进行搜索:

.query.filter(Model.column.ilike("ganye"))

对@ples 的回答进行了改进,如果您只指定所需的列,这个查询将变得更短:

user = models.User.query.with_entities(models.User.username).\
filter(models.User.username.ilike("%ganye%")).all()

如果需要使用 Flask 的 jsonify 来实现 AJAX 目的,那么上面的例子非常有用,然后在你的 javascript 中使用 结果访问它:

from flask import jsonify
jsonify(result=user)

你可以的

user = db.session.query(User).filter_by(func.lower(User.username)==func.lower("GANYE")).first()

或者你可以使用 ilike 函数

 user = db.session.query(User).filter_by(User.username.ilike("%ganye%")).first()

如果它适合您的用例,您可以考虑在列上设置一个自定义的 校对,这样该列就会以不区分大小写的方式自动处理比较。

值得注意的是:

  • 排序规则将应用于该列上的所有查询
  • 排序也适用于 ORDER BY条款
  • 排序规则可以在查询中直接指定,而不是在列上定义
    • 这可能会导致性能损失
  • 排序规则的定义往往是 RDBMS/locale/language 特定的-请参考相关文档
  • 排序规则名称可能不能在不同的 RDBMS 之间移植
  • 可用的排序规则属性可能因 RDBMS 而异

换句话说,在使用这个特性之前,请参考 RDBMS 的文档。

这个示例脚本展示了如何为 MySQL、 Postgreql (注意特殊大小写)和 Sqlite 使用排序规则; 每个 RDBMS 返回查询值的所有三个可能的结果。

import sqlalchemy as sa
from sqlalchemy import orm


data = {
'mysql': ('mysql:///test', 'utf8mb4_general_ci'),
'postgresql': ('postgresql:///test', 'coll'),
'sqlite': ('sqlite://', 'NOCASE'),
}




for dialect, (uri, collation) in data.items():
Base = orm.declarative_base()


class Test(Base):
__tablename__ = 't16573095'


id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String(32, collation=collation))


engine = sa.create_engine(uri, echo=False, future=True)
Base.metadata.drop_all(engine)


if dialect == 'postgresql':
# Postgres collations are more complicated
# - read the docs!
with engine.begin() as conn:
conn.execute(sa.text('DROP COLLATION IF EXISTS coll'))
stmt = """CREATE COLLATION coll (provider='icu', locale='und-u-ks-level2', deterministic=false)"""
conn.execute(sa.text(stmt))


Base.metadata.create_all(engine)
Session = orm.sessionmaker(engine, future=True)


with Session.begin() as s:
instances = [Test(name=name) for name in ['GANYE', 'ganye', 'gAnYe']]
s.add_all(instances)


with Session() as s:
results = s.execute(sa.select(Test.name).where(Test.name == 'GaNyE')).scalars()
print(f'{dialect:-<12}')
for name in results:
print(name)
print('-' * 12)

若要在查询中指定排序规则,请使用属性的 整理一下方法:

with Session() as s:
query = sa.select(Test).where(Test.name.collate('coll') == 'GaNyE')
results = s.execute(query)

我认为最好的解决办法是

func.lower(User.username).contains(username.lower())

它会产生 sql 像

WHERE (lower(user.username) LIKE '%%' || %s || '%%')

这意味着您的 dbusername将被转换为小写,并且 Python 值 username也将被转换为小写。所以现在您不必担心案件的敏感性

如果你的 usernameSara Smith,它将为 arasarSara或事件 a S工作