2015-02-12 171 views
0

如何處理數據庫中字符串到域模型中bool的映射。考慮一個例子,將硬幣翻轉存儲在數據庫中。對於通常只有兩個值的情況,如磁頭尾部將db varchar映射到域對象bool

注:我意識到這是在大多數情況下還可以存儲在數據庫中的bool更好,但認爲這是一個學術活動)

我想模型落得「正面」在數據庫中,而「尾巴」在數據庫中最終爲False in the model。

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

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