使用ZCA和SQLAlchemy

时间:2015-10-23 10:30:54

标签: python sqlalchemy zope zope.component

实际上我正在使用python 3.4设计一个大型桌面应用程序。 我选择了端口和适配器架构,就像六边形架构一样。 它的主要目的是使用可重用的组件。

要组织代码并制定一些规则,我们将使用Zope组件架构(ZCA)

所以要做一些POC,我正在创建数据库组件。 但是使用ORM的事实阻止了我。我的意思是我设计了一些看起来像的数据库组件:

-IDatabase -IDatabaseConfig -IEntity -IKey -IReader -IWriter ... 和实施。

SQLAlchemy管理很多东西,我不知道如何使我的组件可重用。

我找到了这段代码:

#Reflect each database table we need to use, using metadata
class Customer(Base):
    __table__ = Table('Customers', metadata, autoload=True)
    orders = relationship("Order", backref="customer")

class Shipper(Base):
    __table__ = Table('Shippers', metadata, autoload=True)
    orders = relationship("Order", backref="shipper")

class Product(Base):
    __table__ = Table('Products', metadata, autoload=True)
    supplier = relationship('Supplier', backref='products')
    category = relationship('Category', backref='products') 

但我认为这段代码很难与SQLAlchemy结合使用。 那么我应该对我的架构使用什么方法呢?

由于实体必须是应用程序的中心(域层),如果我需要更改我的数据库组件而不使用SQLAlchemy,那么该解决方案会出现问题?

我对所有建议持开放态度。

1 个答案:

答案 0 :(得分:0)

我使用ORM作为实体对象并将Adapters放在它上面:

interfaces.py中的某个地方定义了API:

from zope.interface import Interface

class IEntity(Interface):

    def pi_ing():
        '''makes the entity go "pi-ing" '''

定义了数据库模型:

class EntityA(Base):       
    # .. table and relationship definitions are here

实施API的其他地方:

from zope.interface import implementer
from zope.component import adapter, getGlobalSiteManager

class EntityAPI(object):

    def __init__(self, instance):
        self.instance = instance

    def pi_ing(self):
        # make "pi_ing"


@implementer(IEntityAProtocol)
@adapter(int)
def get_entity_a_by_id(id):
    return EntityAPI(session().query(EntityA).get(id))

getGlobalSiteManager().registerAdapter(get_entity_a_by_id)

现在一切都已到位。代码的业务逻辑中的某个地方 当你获得entity_a的id时,你可以这样做:

from interfaces import IEntityAProtocol

def stuff_which_goes_splat():        
    # ...
    entity_id = got_from_somewhere()
    IEntityProtocol(entity_id).pi_ing()

现在,您可以完全独立地实现接口,数据库实体和API逻辑。好的方面是,你不必只调整像对象的int ID这样的原始东西,你可以适应任何东西,只要你能实现从你的适配器到数据库实体的直接转换。

警告:当然,相对于执行时间点,getGlobalSiteManager().registerAdapter(get_entity_a_by_id)必须已经被调用。