如何使用 SQLAlchemy 仅创建一张表?

问题描述 投票:0回答:4

我无法使用 SQLAlchemy 创建单个表。

我可以通过调用

Base.metadata.create_all(engine)
来创建它,但是随着表数量的增长,这个调用需要很长时间。

我动态创建表类,然后填充它们。

from sqlalchemy import create_engine, Column, Integer, Sequence, String, Date, Float, BIGINT
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

class HistoricDay():

    id = Column(Integer, Sequence('id_seq'), primary_key=True)
    #  Date, Open, High, Low, Close, Volume, Adj Close
    date = Column(Date)
    open = Column(Float)
    high = Column(Float)
    low = Column(Float)
    close = Column(Float)
    volume = Column(BIGINT)
    adjClose = Column(Float)

    def __init__(self, date, open, high, low, close, volume, adjClose):
        self.date = date
        self.open = open
        self.high = high
        self.low = low
        self.close = close
        self.volume = volume
        self.adjClose = adjClose

def build_daily_history_table_repr(self):
        return "<"+self.__tablename__+"('{}','{}','{}','{}','{}','{}','{}','{}')>".format(self.id, self.date, self.open, self.high, self.low, self.close, self.volume, self.adjClose)

def build_daily_history_table(ticket):
    classname = ticket+"_HistoricDay"
    globals()[classname] = type(classname, (HistoricDay,Base), {'__tablename__' : ticket+"_daily_history"})
    setattr(globals()[classname], '__repr__', build_daily_history_table_repr)

# Initialize the database :: Connection & Metadata retrieval
engine = create_engine('mysql+cymysql://root@localhost/gwc?charset=utf8&use_unicode=0', pool_recycle=3600) # ,echo = True

# SqlAlchemy :: Session setup
Session = sessionmaker(bind=engine)

# Create all tables that do not already exist
Base.metadata.create_all(engine)

# SqlAlchemy :: Starts a session
session = Session()

ticketList = getTicketList()

for ticket in ticketList:
    build_daily_history_table(ticket)
    class_name = ticket+"_HistoricDay"

    meta_create_all_timer = time.time()
    # Create all tables that do not already exist
    # globals()[class_name]('2005-07-24',0,0,0,0,0,0).create(engine)  #doesn't work
    #(globals()[class_name]).__table__.create(engine) #doesn't work
    # session.commit() #doesn't work

    #Base.metadata.create_all(engine) # works but gets very slow
    print("  meta_create_all_timer {}s".format(time.time()-meta_create_all_timer))

    data = getData(ticket)

    for m_date, m_open, m_close, m_high, m_low, m_volume, m_adjClose in data:
        entry = globals()[class_name](m_date, m_open, m_high, m_low, m_close, m_volume, m_adjClose)
        session.add(entry)

    session.commit()

我在文档中看到你可以这样做

engine = create_engine('sqlite:///:memory:')

meta = MetaData()

employees = Table('employees', meta,
    Column('employee_id', Integer, primary_key=True),
    Column('employee_name', String(60), nullable=False, key='name'),
    Column('employee_dept', Integer, ForeignKey("departments.department_id"))
)
employees.create(engine)

但是,我无法弄清楚如何使用

Table
做同样的事情。

如何使用继承自

declarative_base()

的类来做到这一点?

    

python mysql python-3.x sqlalchemy
4个回答
40
投票
上面, declarative_base() 可调用函数返回一个新的基类 所有映射的类都应该继承。当类定义为 完成后,将生成一个新的 Table 和 mapper()。

结果表和映射器可通过

declarative_base()

和访问

__table__
属性


(来自
这里

因此:

__mapper__

输出:

def build_daily_history_table(ticket): classname = ticket + "_HistoricDay" ticket = type(classname, (Base, HistoricDay), {'__tablename__' : ticket+"_daily_history"}) ticket.__repr__ = build_daily_history_table_repr return ticket build_daily_history_table("test").__table__.create(bind = engine)

归功于 
javex 的

评论/更正,或者我可能会提出类似的建议: 2013-10-04 22:36:53,263 INFO sqlalchemy.engine.base.Engine CREATE TABLE test_daily_history ( id INTEGER NOT NULL, date DATE, open FLOAT, high FLOAT, low FLOAT, close FLOAT, volume BIGINT, "adjClose" FLOAT, PRIMARY KEY (id) ) 2013-10-04 22:36:53,263 INFO sqlalchemy.engine.base.Engine () 2013-10-04 22:36:53,263 INFO sqlalchemy.engine.base.Engine COMMIT

建议:

Base.metadata.tables["ticket_daily_history"].create(bind = engine)

中使用的方法可能是最不优雅的做事方式之一,主要是因为它污染/混乱了

命名空间


25
投票
build_daily_history_table

参数赋予

tables
方法就足够了。

create_all()

table_objects 等于:

Base.metadata.create_all(engine, tables=table_objects)

table_objects = [HistoricDay.__table__]

我在这里展示了一张桌子。您可以根据需要增加桌子数量。

参考:

http://docs.sqlalchemy.org/en/latest/core/metadata.html#sqlalchemy.schema.MetaData.create_all


12
投票

table_objects = [Base.metadata.tables["historicday"]]

使用 
Base.metadata.create_all(db_engine, Base.metadata.tables.values(),checkfirst=True)

创建一个目标表。


table_name

它与
Base.metadata.create_all(db_engine, Base.metadata.tables[table_name],checkfirst=True)

完美配合。


declarative_base



0
投票

from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() TABLE_PREFIX = "decision_" class Stock(Base): __tablename__ = '{}stocks'.format(TABLE_PREFIX) id = Column(Integer, primary_key=True) name = Column(String) class StagePerformance(Base): __tablename__ = '{}stage_performance'.format(TABLE_PREFIX) id = Column(Integer, primary_key=True) date = Column(DateTime) stock = relationship("Stock", back_populates="stage_performances") period = Column(Integer ) open = Column(Float) high = Column(Float) low = Column(Float) close = Column(Float) change_ratio = Column(Float) turnover = Column(Float) volume = Column(Float)

在此之后,您可以运行(如果您正在运行异步):

def table_creator(table_name: str, selectors: list) -> str: columns = [ "id INTEGER PRIMARY KEY AUTO_INCREMENT", ... ] for selector in selectors: columns.append(f"`{selector.name}` VARCHAR(255) {'NOT NULL' if selector.required else ''}") query = f"CREATE TABLE {table_name} ({', '.join(columns)})" print(query) return query

这将创建您需要的表。

但是,因此,您将无法立即使用表 ORM 对象。

欢迎所有建议。我自己也一直在努力解决这个问题。

© www.soinside.com 2019 - 2024. All rights reserved.