Je ne parviens pas à créer une seule table à l'aide de SQLAlchemy.
Je peux le créer en appelant Base.metadata.create_all(engine)
mais à mesure que le nombre de tables augmente, cet appel prend beaucoup de temps.
Je crée des classes de table à la volée, puis je les remplis.
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()
J'ai vu dans le documentation que vous pouvez faire
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)
Cependant, je ne suis pas en mesure de comprendre comment faire la même chose que Table
, avec declarative_base()
.
Comment puis-je faire cela avec des classes qui héritent de declarative_base()
?
Ci-dessus, l'appelable declarative_base () renvoie une nouvelle classe de base dont toutes les classes mappées devraient hériter. Une fois la définition de classe terminée, une nouvelle table et un nouveau mappeur () auront été générés.
La table et le mappeur résultants sont accessibles via
__table__
et__mapper__
les attributs
(De ici )
Par conséquent:
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)
Sortie:
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
Le crédit revient à javex's commentaire/correction ou j'aurais pu suggérer quelque chose de semblable à:
Base.metadata.tables["ticket_daily_history"].create(bind = engine)
Conseil:
L'approche utilisée dans build_daily_history_table
pourrait être l'une des façons les moins élégantes de faire les choses, principalement parce qu'elle pollue/encombre le namespace .
Pour créer des tables spécifiques, il suffit de donner le paramètre tables
à la méthode create_all()
.
Base.metadata.create_all(engine, tables=table_objects)
table_objects est égal à:
table_objects = [HistoricDay.__table__]
ou
table_objects = [Base.metadata.tables["historicday"]]
J'ai montré une table ici. Vous pouvez augmenter le nombre de tables comme vous le souhaitez.
Référence: http://docs.sqlalchemy.org/en/latest/core/metadata.html#sqlalchemy.schema.MetaData.create_all
Créez toutes les tables qui n'existent pas avec une seule ligne. Il vérifiera si la table existe d'abord par défaut.
Base.metadata.create_all(db_engine, Base.metadata.tables.values(),checkfirst=True)
Créez une table cible avec table_name
.
Base.metadata.create_all(db_engine, Base.metadata.tables[table_name],checkfirst=True)
Cela fonctionne parfaitement avec declarative_base
.
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
TABLE_PREFIX = "decision_"
class Stock(Base):
__table= '{}stocks'.format(TABLE_PREFIX)
id = Column(Integer, primary_key=True)
name = Column(String)
class StagePerformance(Base):
__table= '{}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)