![](/img/trans.png)
[英]SQLAlchemy TypeDecorator for BigInteger returns Decimal?
[英]Alternate preprocessing method to TypeDecorator in SQLAlchemy
我在插入数据库之前使用sqlalchemy.types.TypeDecorator
预处理文本字段。 除非我将like
表达式与包含百分比的比较器一起使用(例如User.name.like('%bar%')
),否则它会很好用,因为在执行查询之前,这些百分比已由process_bind_param()
剥离。
这使我认为TypeDecorator
不是实现预处理指令的正确方法。 是否有:
process_bind_param
的方法? 这是扩充类型的最小实现:
import re
from sqlalchemy import Column, Integer, Text
import sqlalchemy.types as types
from sqlalchemy.ext.declarative import declarative_base
class AlphaOnlyText(types.TypeDecorator):
"""Replaces everything that's not A-Za-z or space with nothing."""
impl = types.Text
def process_bind_param(self, text, dialect):
return None if text is None else re.sub(r'[^A-Za-z\-\s]', '' , text.strip())
Base = declarative_base()
class User(Base):
__tablename__ = 'User'
id = Column(Integer, primary_key=True)
name = Column(AlphaOnlyText, unique=True)
def __repr__(self):
return "<User(name='{}')>".format(self.name)
以下代码演示了有效的插入和查询:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# Create the database
engine = create_engine('sqlite://', echo=True)
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
# Add a row
session.add(User(name='foobar'))
# Query the row
session.query(User).filter_by(name=='foobar').all()
# [<User(name='foobar')>]
这是失败的地方-当我使用like
表达式时,将运行该列的process_bind_param
,在将过滤器添加到查询之前去除百分比:
filter = User.name.like('%bar%')
filter.compile().params
# {'name_1': '%bar%'} <-- The '%' are still here
session.query(User).filter(filter).all()
# Nothing. (Percent symbols are stripped, so '%bar%' ==> 'bar'.)
# If your engine was created with `echo=True`
# you can see this directly in the logging statements
如果绕过ORM,我可以通过直接SQL来获得所需的内容,但我不想要求用户遵循此路线。
query_template = "SELECT * FROM user WHERE name LIKE :nm;"
session.execute(query_template, {'nm':'%bar%'}).fetchall()
# [(1, 'foobar')]
使用验证器的选项1是正确的。 TypeDecorator
更适合于实际修改数据类型-例如,为用户腌制某种东西以将其作为字符串存储到数据库中,然后将其无缝地解开回到类中。
在这种情况下, @validates
装饰器将对相同类型的数据执行验证。 验证器的功能不是拒绝/标记/记录不可接受的格式化数据(可能是验证的预期主要用例),而是将相同类型的不可接受数据转换为可接受的数据。
这是代码:
import re
from sqlalchemy import Column, Integer, Text
#import sqlalchemy.types as types ## Don't need this anymore
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import validates ## This one for the validator
Base = declarative_base()
class User(Base)
__tablename__ = 'User'
id = Column(Integer, primary_key=True)
name = Column(Text, unique=True)
@validates("name")
def alpha_only(self, key, value):
return None if value is None else re.sub(r'[^A-Za-z\-\s]', '' , value.strip())
def __repr__(self):
return "<User(name='{}')>".format(self.name)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.