2013-10-04 13 views
24

Ich kann mit SQLAlchemy keine einzelne Tabelle erstellen.Wie erstellt man nur eine Tabelle mit SQLAlchemy?

Ich kann es erstellen, indem ich Base.metadata.create_all(engine) aufrufen, aber wie die Anzahl der Tabelle wächst, dauert dieser Aufruf eine lange Zeit.

Ich erstellen Tabellenklassen im laufenden Betrieb und füllen sie dann.

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://[email protected]/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() 

sah ich in der documentation, dass Sie jedoch

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) 

tun kann, bin ich, um herauszufinden, nicht in der Lage, wie die gleiche Sache zu tun, wie Table tut, mit declarative_base().

Wie kann ich das mit Klassen, die von declarative_base() erben?

+1

sollte es 'HistoricDay (Base)' –

+0

Nein sein, da HistoricDay kein Attribut Tabellenname hat. Die generierte Klasse erbt von Basis: Globals() [classname] = Typ (classname, (HistoricDay, Basis), { 'Tabellenname': Ticket + "_ daily_history"}) – Lazik

Antwort

17

Above, the declarative_base() callable returns a new base class from which all mapped classes should inherit. When the class definition is completed, a new Table and mapper() will have been generated.

The resulting table and mapper are accessible via __table__ and __mapper__ attributes

(Von here)

Deshalb:

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) 

Ausgang:

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 

Kredit geht an javex's Kommentar/Korrektur oder I migh t haben so etwas wie vorgeschlagen:

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

Advise:

Die in build_daily_history_table verwendete Ansatz eines der am wenigsten elegante Weise sein könnte, Dinge zu tun, in erster Linie aus dem Grund, dass es verschmutzt/unübersichtlich die namespace.

+0

habe ich versucht, aber 'Traceback (jüngste Aufforderung zuletzt) : File "autoPopulate.py", Linie 493, in m_init() File "autoPopulate.py", Leitung 422, in m_init state = success_state (ticket) File "autoPopulate.py", Leitung 306, in success_state Globals() [class_name] .Create (Motor) Attribute: Typ Objekt 'HMN_HistoricDay' hat kein Attribut ‚create'' – Lazik

+28

' HistoricDay .__ Tabelle __ erstellen (Motor) ' – javex

+0

@javex +1 guten Fang –

Verwandte Themen