IT

케이스 무감각 플라스크-SQLlchemy 쿼리

itgroup 2023. 10. 15. 17:13
반응형

케이스 무감각 플라스크-SQLlchemy 쿼리

플라스크-SQ를 사용하고 있습니다.사용자 데이터베이스에서 쿼리하는 LAlchemy(LAlchemy); 그러나,

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()

위의 예는 AJAX 목적으로 Flask의 jsonify를 사용한 후 자바스크립트에서 data를 사용하여 액세스해야 하는 경우에 매우 유용합니다. 결과:

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 like 를 만들어 낼 것입니다.

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

이것은 당신의 db를 의미합니다.username소문자와 당신의 파이썬 값으로 변환될 것입니다.username또한 소문자로 변환됩니다.따라서 이제 환자의 민감도에 대해 걱정할 필요가 없습니다.

당신의usernameSara Smith잘 될 것입니다.ara,sar,Sara또는 이벤트a S

사용 사례에 적합한 경우 열이 대소문자를 구분하지 않는 방식으로 비교를 자동으로 처리하도록 열에 사용자 정의 대조를 설정하는 것을 고려해 볼 수 있습니다.

주목할 점은 다음과 같습니다.

  • 콜렉션은 열에 있는 모든 쿼리에 적용됩니다.
  • 그 조합은 에 적용될 것입니다.ORDER BY조항들도
  • 콜렉션은 열에 정의되지 않고 쿼리에 직접 지정될 수 있습니다.
    • 이로 인해 성능 패널티가 발생할 수 있습니다.
  • 대조 정의는 RDBMS / 로케일 / 언어별인 경향이 있음 - 관련 문서 참조
  • 서로 다른 RDBMS 간에 콜렉션 이름을 이동할 수 없습니다.
  • RDBMS에 따라 사용 가능한 대조 특성이 달라질 수 있음

즉, 이 기능을 사용하기 전에 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)

조회에서 대조를 지정하려면 속성의 대조 방법을 사용합니다.

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}%")
    )
    

언급URL : https://stackoverflow.com/questions/16573095/case-insensitive-flask-sqlalchemy-query

반응형