我正在使用SQLAlchemy 1.0.6和Python 2.7.6。在我从上一篇文章(Dynamic Datasets and SQLAlchemy)中收集到的伟大见解之后,我现在希望模块化我的代码,以便更容易地实现到我的框架中。从这个完整的代码
from time import time
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class Empty_Init():
def __init__(self, **kwargs):
for k,v in kwargs.items():
#This class and the structure of the table need to be sync'd.
if hasattr(self, k):
setattr(self, k, v)
else:
if k not in engine.execute("SELECT * FROM `{tbl}`".format(tbl = self.__tablename__))._metadata.keys:
engine.execute("ALTER TABLE `{tbl}` ADD COLUMN {col} {typ}".format(
tbl = self.__tablename__,
col = k,
typ = "INT" if type(v) is int else ("DOUBLE" if type(v) is float else "VARCHAR")))
setattr(self.__class__, k, Column(k, String))
setattr(self, k, v)
class Listing(Empty_Init, Base):
__tablename__ = 'Listings'
__table_args__ = {'sqlite_autoincrement': True}
id = Column(Integer, primary_key=True, nullable=False)
make = Column(String)
model = Column(String)
year = Column(Integer)
t = time()
engine = create_engine('sqlite:///')
Base.metadata.create_all(engine)
session = sessionmaker()
session.configure(bind=engine)
s = session()
try:
data = {'make':'Chevy',
'model' : 'Corvette',
'year' : 1964,
'doors' : 2,
'price' : 50000}
record = Listing(**data)
s.add(record)
data = {'make':'Chevy',
'model' : 'Camaro',
'year' : 1967,
'doors' : 2,
'HP' : 375,
"0-60" : 6.1}
record = Listing(**data)
s.add(record)
s.commit() #attempt to commit the changes
except:
s.rollback() #rollback the changes on error
finally:
s.close() #Close the connection
print str(time() - t) + " s."
(注意:Empty_Init类的目的是将它继承到其他表,如清单类中所示。)
我想
import
认为第一个目标需要在第二个目标之前实现,这就是我遇到的问题
from time import time
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
class DataBase(object):
def __init__(self):
self.Base = declarative_base()
self.engine = create_engine('sqlite:///')
self.session = sessionmaker()
self.session.configure(bind=self.engine)
self.s = self.session()
self.Base.metadata.create_all(self.engine)
def Add_Record(self, data):
record = Listing(self.engine, self.Base, **data)
self.s.add(record)
def Commit(self):
self.s.commit()
class Empty_Init():
def __init__(self, engine, Base, **kwargs):
for k,v in kwargs.items():
#This class and the structure of the table need to be sync'd.
if hasattr(self, k):
setattr(self, k, v)
else:
if k not in engine.execute("SELECT * FROM `{tbl}`".format(tbl = self.__tablename__))._metadata.keys:
engine.execute("ALTER TABLE `{tbl}` ADD COLUMN {col} {typ}".format(
tbl = self.__tablename__,
col = k,
typ = "INT" if type(v) is int else ("DOUBLE" if type(v) is float else "VARCHAR")))
setattr(self.__class__, k, Column(k, String))
setattr(self, k, v)
class Listing(Empty_Init):
__tablename__ = 'Listings'
__table_args__ = {'sqlite_autoincrement': True}
id = Column(Integer, primary_key=True, nullable=False)
make = Column(String)
model = Column(String)
year = Column(Integer)
t = time()
engine = create_engine('sqlite:///')
DBC = DataBase()
data = {'make':'Chevy',
'model' : 'Corvette',
'year' : 1964,
'price' : 50000}
DBC.Add_Record(data)
data = {'make':'Chevy',
'model' : 'Camaro',
'year' : 1967,
'HP' : 375,
"0-60" : 6.1}
DBC.Add_Record(data)
DBC.Commit()
print str(time() - t) + " s."
运行此命令会提供以下完整的Traceback
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/dist-packages/spyderlib/widgets/externalshell/sitecustomize.py", line 540, in runfile
execfile(filename, namespace)
File "/home/manny/sqlalchemy_basic_master_class.py", line 65, in <module>
DBC.Add_Record(data)
File "/home/manny/sqlalchemy_basic_master_class.py", line 23, in Add_Record
record = Listing(self.engine, self.Base, **data)
File "/home/manny/sqlalchemy_basic_master_class.py", line 40, in __init__
if k not in engine.execute("SELECT * FROM `{tbl}`".format(tbl = self.__tablename__))._metadata.keys:
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1987, in execute
return connection.execute(statement, *multiparams, **params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 906, in execute
return self._execute_text(object, multiparams, params)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1054, in _execute_text
statement, parameters
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1341, in _handle_dbapi_exception
exc_info
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/util/compat.py", line 199, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/sqlalchemy/engine/default.py", line 450, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: Listings [SQL: 'SELECT * FROM `Listings`']
我理解错误说的是什么(数据库是创建的,但是没有表),但为什么呢?为什么SQLAlchemy没有创建表?我在DataBase __init__
下以相同的顺序执行了相同的代码。更令人费解的是,如果我运行第一个代码,那么通过继承DataBase
和Base
SQLAlchemy类来初始化engine
类,如此
class DataBase(object):
def __init__(self, Base, engine):
self.Base = Base
self.engine = engine
self.session = sessionmaker()
self.session.configure(bind=self.engine)
self.s = self.session()
self.Base.metadata.create_all(self.engine)
Base = declarative_base()
engine = create_engine('sqlite:///')
DBC = DataBase(Base, engine)
并运行它的方法,它完美地写入数据库,所以我强烈怀疑我没有正确地继承SQLAlchemy的类(在第二个代码中),或者在很小的程度上,我&#39 ;不要让SQLAlchemy通过将它包装成一个类来进行幕后魔术工作 - 我只是不明白为什么。我错过了一些明显的东西吗?
答案 0 :(得分:0)
更新:我认为我认为我尝试构建课程的方式不是让SQLAlchemy的幕后魔术工作正确。因此,在使用类继承之后,这个完整的代码可以完美地运行:
from time import time
from sqlalchemy import Column, String, Integer
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class DataBase(object):
def __init__(self, Base):
self.Base = Base
self.engine = create_engine('sqlite:///')
self.session = sessionmaker()
self.session.configure(bind=self.engine)
self.s = self.session()
self.Base.metadata.create_all(self.engine)
def Add_Record(self, data):
record = Listing(self.engine, **data)
self.s.add(record)
def Commit(self):
self.s.commit()
def Close(self):
self.s.close()
class Empty_Init():
def __init__(self, engine, **kwargs):
#This class and the structure of the table need to be sync'd.
for k,v in kwargs.items():
if hasattr(self, k): #if the class already has the attribute initialized,
setattr(self, k, v) # then assign it the new value
else: # if it doesn't...
if k not in engine.execute("SELECT * FROM `{tbl}`".format(tbl = self.__tablename__))._metadata.keys:
engine.execute("ALTER TABLE `{tbl}` ADD COLUMN {col} {typ}".format(
tbl = self.__tablename__,
col = k,
typ = "INT" if type(v) is int else ("DOUBLE" if type(v) is float else "VARCHAR")))
setattr(self.__class__, k, Column(k, String))
setattr(self, k, v)
class Listing(Empty_Init, Base):
__tablename__ = 'Listings'
__table_args__ = {'sqlite_autoincrement': True}
id = Column(Integer, primary_key=True, nullable=False)
make = Column(String)
model = Column(String)
year = Column(Integer)
t = time()
DBC = DataBase(Base)
data = {'make':'Chevy',
'model' : 'Corvette',
'year' : 1964,
'price' : 50000}
DBC.Add_Record(data)
data = {'make':'Chevy',
'model' : 'Camaro',
'year' : 1967,
'doors' : 2,
'wheels_rwd' : 4.1,
"test" : "bladads"}
DBC.Add_Record(data)
DBC.Commit()
DBC.Close()
print str(time() - t) + " s."
请注意类继承的轻微变化。
现在第一个目标已经完成,我想继续将DataBase
,Empty_Init
和Listing
放入外部模块。这部分有点棘手,但这是一起如何协同工作
main.py
from time import time
from datetime import datetime
import sqla_lib
t = time()
DBC = sqla_lib.DataBase(sqla_lib.Base)
data = {'make':'Chevy',
'model' : 'Corvette',
'year' : 1964,
'price' : 50000}
DBC.Add_Record(data)
data = {'make':'Chevy',
'model' : 'Camaro',
'year' : 1967,
'doors' : 2,
'wheels_rwd' : 4.1,
"test" : "bladads"}
DBC.Add_Record(data)
DBC.Commit()
DBC.Close()
print str(time() - t) + " s."
sqla_lib.py
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, String, Integer
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
Base = declarative_base()
class DataBase(object):
def __init__(self, Base):
self.Base = Base
self.engine = create_engine('sqlite:///')
self.session = sessionmaker()
self.session.configure(bind=self.engine)
self.s = self.session()
self.Base.metadata.create_all(self.engine)
def Add_Record(self, data):
record = self.Listing(self.engine, **data)
self.s.add(record)
def Commit(self):
self.s.commit()
def Close(self):
self.s.close()
class Empty_Init():
def __init__(self, engine, **kwargs):
#This class and the structure of the table need to be sync'd.
for k,v in kwargs.items():
if hasattr(self, k): #if the class already has the attribute initialized,
setattr(self, k, v) # then assign it the new value
else: # if it doesn't...
if k not in engine.execute("SELECT * FROM `{tbl}`".format(tbl = self.__tablename__))._metadata.keys:
engine.execute("ALTER TABLE `{tbl}` ADD COLUMN {col} {typ}".format(
tbl = self.__tablename__,
col = k,
typ = "INT" if type(v) is int else ("DOUBLE" if type(v) is float else "VARCHAR")))
setattr(self.__class__, k, Column(k, String))
setattr(self, k, v)
class Listing(Empty_Init, Base):
__tablename__ = 'Listings'
__table_args__ = {'sqlite_autoincrement': True}
id = Column(Integer, primary_key=True, nullable=False)
make = Column(String)
model = Column(String)
year = Column(Integer)
由于我还是SQLAlchemy的新人,我欢迎你提出任何意见。但由于这解决了我的两个目标,我将把这个问题标记为已解决。我希望将来可以帮助某人。