将 db varchar 映射到域对象 bool
Mapping db varchar to domain object bool
如何处理数据库中的字符串到域模型中的布尔值的映射。考虑一个例子,将抛硬币存储在数据库中。对于通常只有两个值的情况,例如 heads 或 tails。
(注意: 我意识到在大多数情况下最好在数据库中存储布尔值,但认为这是一个学术练习)
我希望模型中的 True 在数据库中最终为 "heads",并且 "tails" 在数据库中最终在模型中为 False。
from sqlalchemy.orm import mapper, sessionmaker
from sqlalchemy import Table, MetaData, Column, Integer, String, create_engine
from unittest import TestCase
class Foo(object):
def __init__(self, id, is_heads):
self.id = id
self.is_heads = is_heads
metadata = MetaData()
db_foo = Table(
'foo', metadata,
Column('id', Integer, primary_key=True),
Column('side', String(5), nullable=False)) # heads or tails
def data_map():
# what do I need to do here?
mapper(Foo, db_foo)
class TestMaps(TestCase):
def test_map(self):
# Setup
engine = create_engine('sqlite:///:memory:', echo=True)
metadata.create_all(engine, tables=[db_foo])
Session = sessionmaker(bind=engine)
session = Session()
data_map()
expected = Foo(1, False)
# Exercise
session.add(expected)
session.flush()
actual = session.query(Foo).first()
# Verify
self.assertEqual(expected, actual)
查看文档的 Augmenting Existing Types 部分。以下应该可以解决问题:
import sqlalchemy.types as types
class CoinFlipDataType(types.TypeDecorator):
impl = types.String
def process_bind_param(self, value, dialect):
if value is None:
return None
assert value in (True, False)
return 'heads' if value else 'tails'
def process_result_value(self, value, dialect):
if value is None:
return None
assert value in ('heads', 'tails'), value
return value == 'heads'
def copy(self):
return CoinFlipDataType(self.impl.length)
def data_map():
mapper(Foo, db_foo, properties={'is_heads': db_foo.c.side})
db_foo = Table(
'foo', metadata,
Column('id', Integer, primary_key=True),
Column('side', CoinFlipDataType(5), nullable=False))
如何处理数据库中的字符串到域模型中的布尔值的映射。考虑一个例子,将抛硬币存储在数据库中。对于通常只有两个值的情况,例如 heads 或 tails。
(注意: 我意识到在大多数情况下最好在数据库中存储布尔值,但认为这是一个学术练习)
我希望模型中的 True 在数据库中最终为 "heads",并且 "tails" 在数据库中最终在模型中为 False。
from sqlalchemy.orm import mapper, sessionmaker
from sqlalchemy import Table, MetaData, Column, Integer, String, create_engine
from unittest import TestCase
class Foo(object):
def __init__(self, id, is_heads):
self.id = id
self.is_heads = is_heads
metadata = MetaData()
db_foo = Table(
'foo', metadata,
Column('id', Integer, primary_key=True),
Column('side', String(5), nullable=False)) # heads or tails
def data_map():
# what do I need to do here?
mapper(Foo, db_foo)
class TestMaps(TestCase):
def test_map(self):
# Setup
engine = create_engine('sqlite:///:memory:', echo=True)
metadata.create_all(engine, tables=[db_foo])
Session = sessionmaker(bind=engine)
session = Session()
data_map()
expected = Foo(1, False)
# Exercise
session.add(expected)
session.flush()
actual = session.query(Foo).first()
# Verify
self.assertEqual(expected, actual)
查看文档的 Augmenting Existing Types 部分。以下应该可以解决问题:
import sqlalchemy.types as types
class CoinFlipDataType(types.TypeDecorator):
impl = types.String
def process_bind_param(self, value, dialect):
if value is None:
return None
assert value in (True, False)
return 'heads' if value else 'tails'
def process_result_value(self, value, dialect):
if value is None:
return None
assert value in ('heads', 'tails'), value
return value == 'heads'
def copy(self):
return CoinFlipDataType(self.impl.length)
def data_map():
mapper(Foo, db_foo, properties={'is_heads': db_foo.c.side})
db_foo = Table(
'foo', metadata,
Column('id', Integer, primary_key=True),
Column('side', CoinFlipDataType(5), nullable=False))