在SQLAlchemy中用什么类型存储字节字符串?

时间:2014-11-29 01:33:23

标签: python postgresql sqlalchemy

我尝试使用SQLAlchemy在PostgreSQL数据库中存储字节字符串。

我的模型看起来像这样:

class UserAccount(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String)
    password_hash = db.Column(db.String)
    password_salt = db.Column(db.String)

我希望password_hashpassword_salt都是字节字符串(即str,因为我使用的是Python 2.7),但即使我将字节传递给它,SQLAlchemy似乎也将它们转换为进入unicode。我也尝试在模型中使用convert_unicode=False,但我得到的结果相同。

我在SQLAlchemy模型中用什么来存储字节?

2 个答案:

答案 0 :(得分:16)

使用LargeBinary类型,它将在PostgreSQL上使用bytea类型。如果您只使用PostgreSQL,也可以直接使用BYTEA类型。

还有其他SQL标准类型,例如BINARY,但它通常更容易使用LargeBinary,因为SQLAlchemy将为每个数据库使用首选类型。

答案 1 :(得分:0)

对于较短的字节字符串,您还可以使用TypeDcorator来包装String列类。然后使用您的自定义类型类HexByteString作为Column类型:

from sqlalchemy.types import Column, String, TypeDecorator
from sqlalchemy.ext.declarative import declarative_base


class HexByteString(TypeDecorator):
    """Convert Python bytestring to string with hexadecimal digits and back for storage."""

    impl = String

    def process_bind_param(self, value, dialect):
        if not isinstance(value, bytes):
            raise TypeError("HexByteString columns support only bytes values.")
        return value.hex()

    def process_result_value(self, value, dialect):
        return bytes.fromhex(value) if value else None


Base = declarative_base()

class MyModel(Base):
    data = Column(HexByteString)

然后,您可以将bytes个实例分配给data实例的MyModel属性,它们将被转换为具有十六进制数字的字符串,并在传递给数据库或从数据库传递时返回。当然,这将使存储大小增加一倍,但是当直接查看数据库时,可以更轻松地查看列中存储的内容。

您可以将bytes.hex() / bytes.fromhex()(需要Python 3.5+)替换为任何其他可以安全地将字节存储在Ascii字符串中的编码方案,例如Base64(base64.b64_encode(value).decode() / {{1 }}。