簡體   English   中英

SQLAlchemy:根據屬性將類映射到不同的表

[英]Sqlalchemy: Mapping a class to different tables depending on attribute

我正在嘗試寫入包含以下形式的多個表的現有數據庫

total_usage_<application>:
    id
    version
    date

其中<application>在許多字符串上運行,例如“ appl1”,“ appl2”等。現在,我想使用SQLAlchemy創建單個類,例如

class DBEntry:
    id = ''
    application = ''
    version = ''
    date = ''

這樣DBEntry的實例foo被映射到表"total_usage_" + foo.application 如何做到這一點?

好的,請看下面的示例,它是獨立的,可能會向您顯示一種完成此操作的方法。 它假定您在啟動程序時就知道app_name ,並且假定表名遵循某種命名約定,顯然,您可以適應您的需要,或者通過在每個映射的類中重寫__tablename__來完全手動配置它。
但是主要思想是將配置包裝到一個函數中(也可以使用預先帶有預定義常量的模塊導入來完成)。

from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship, scoped_session, sessionmaker

def camel_to_under(name):
    import re
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()

def configure_database(app_name):
    """ @return: dictionary with all the classes mapped to proper tables for
    specific application.  """
    from sqlalchemy.ext.declarative import declared_attr
    from sqlalchemy.ext.declarative import declarative_base

    class Base(object):
        # docs: http://docs.sqlalchemy.org/en/rel_0_9/orm/extensions/declarative.html#augmenting-the-base
        @declared_attr
        def __tablename__(cls):
            return camel_to_under(cls.__name__) + "_" + app_name

        def __repr__(self):
            attrs = class_mapper(self.__class__).column_attrs # only columns
            # attrs = class_mapper(self.__class__).attrs # show also relationships
            return u"{}({})".format(self.__class__.__name__,
                ', '.join('%s=%r' % (k.key, getattr(self, k.key))
                    for k in sorted(attrs)
                )
            )

    Base = declarative_base(cls=Base)

    class Class1(Base):
        id = Column(Integer, primary_key=True)
        name = Column(String)

    class Class1Child(Base):
        id = Column(Integer, primary_key=True)
        parent_id = Column(Integer, ForeignKey(Class1.id))
        name = Column(String)
        # relationships
        parent = relationship(Class1, backref="children")

    # return locals()
    return {
        "app_name": app_name,
        "Base": Base,
        "Class1": Class1,
        "Class1Child": Class1Child,
        }

def _test():
    """ Little test for the app.  """
    engine = create_engine(u'sqlite:///:memory:', echo=True)
    session = scoped_session(sessionmaker(bind=engine))

    app_name = "app1"
    x = configure_database(app_name)

    # assign real names
    app_name = x["app_name"]
    Base = x["Base"]
    Class1 = x["Class1"]
    Class1Child = x["Class1Child"]

    # create DB model (not required in production)
    Base.metadata.create_all(engine)

    # test data
    cc = Class1Child(name="child-11")
    c1 = Class1(name="some instance", children=[cc])
    session.add(c1)
    session.commit()

_test()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM