将db varchar映射到域对象bool

时间:2015-02-12 00:43:28

标签: python sqlalchemy

如何处理数据库中字符串的映射到域模型中的bool。考虑一个例子,将硬币翻转存储在数据库中。对于通常只有两个值的情况,例如 head tails

注意:我意识到在大多数情况下,将bool存储在数据库中会更好,但请考虑这是学术练习) < / SUP>

我希望模型中的 True 结束数据库中的&#34; head&#34; ,以及&#34; tails&#34; 在数据库中最终为模型中的 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)

1 个答案:

答案 0 :(得分:1)

查看文档的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))