我正在使用 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'>
您可以使用过滤器中的
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"))
改进@plaes的答案,如果您只指定所需的列,这个答案将使查询更短:
user = models.User.query.with_entities(models.User.username).\
filter(models.User.username.ilike("%ganye%")).all()
如果需要使用 Flask 的 jsonify 来实现 AJAX 目的,然后在 javascript 中使用 data.result:
访问它,上面的示例非常有用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()
我认为最好的解决方案是
func.lower(User.username).contains(username.lower())
它会产生像这样的sql
WHERE (lower(user.username) LIKE '%%' || %s || '%%')
这意味着您的 db
username
将转换为小写,您的 python 值 username
也将转换为小写。所以现在你不用担心大小写敏感度了
如果您的
username
是 Sara Smith
它将适用于 ara
、sar
、Sara
或活动 a S
如果适合您的用例,您可以考虑在列上设置自定义排序规则,以便列自动以不区分大小写的方式处理比较。
值得注意的是:
ORDER BY
子句换句话说,在使用此功能之前请查阅 RDBMS 的文档。
此示例脚本展示了如何使用 MySQL、Postgresql(注意特殊情况)和 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)
要在查询中指定排序规则,请使用属性的 collate 方法:
with Session() as s:
query = sa.select(Test).where(Test.name.collate('coll') == 'GaNyE')
results = s.execute(query)
uname = "ganye"
user = models.User.query.filter(User.username.ilikef(f"%{uname}%").first()
return db.session.query(Post).filter(
Post.title.ilike(f"%{search_query}%")
| Post.body.ilike(f"%{search_query}%")
)
对于未来的读者 - SQLAlchemy 2.0 的等效项现在是 ColumnOperators.ilike 方法。 举一个声明性的例子:
class User(DeclarativeBase):
username: str
select(User).where(User.username.ilike("GANYE"))
将渲染为
lower(User.username) LIKE lower("GANYE")