2014-02-23 54 views
1

我正在做一個項目,我需要創建一個具有連接到數據庫並從中獲取數據(我使用SQLite作爲後端)的方法的類實例。 我已經有了一些flask-sqlalchemy的經驗,但是當談到純粹的SQLAlchemy時,我迷失了方向。 概念如下: 用戶創建DataSet的實例,並將路徑作爲__init__參數傳遞給數據庫。如果數據庫已經存在,我只想連接它並執行查詢,如果不存在,我想使用模型創建一個新的查詢。但我無法理解如何去做。從類訪問SQLalchemy

這裏的DataSet代碼:

from os.path import normcase, split, join, isfile 
from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 
import errors 
import trainset 
import testset 


class DataSet: 
    def __init__(self, path_to_set, path_to_db, train_set=False, path_to_labels=None, label_dict=None, 
       custom_name=None): 
     self.__path_to_set = path_to_set 
     self.__label_dict = label_dict 

     if custom_name is None: 
      dbpath = join(path_to_db, 'train.db') 
      if train_set is False: 
       dbpath = join(path_to_db, 'test.db') 
     else: 
      dbpath = join(path_to_db, custom_name) 
     if isfile(dbpath): 
      self.__prepopulated = True 
     else: 
      self.__prepopulated = False 
     self.__dbpath = dbpath 

     if train_set is True and path_to_labels is None: 
      raise errors.InsufficientData('labels', 'specified') 
     if train_set is True and not isfile(path_to_labels): 
      raise errors.InsufficientData('labels', 'found at specified path', path_to_labels) 

    def prepopulate(self): 
     engine = create_engine('sqlite:////' + self.__dbpath) 
     self.__prepopulated = True 

這裏的trainset代碼:

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import Column, String, PickleType, Integer, MetaData 

Base = declarative_base() 
metadata = MetaData() 


class TrainSet(Base): 
    __tablename__ = 'train set' 
    id = Column(Integer, primary_key=True) 
    real_id = Column(String(60)) 
    path = Column(String(120)) 
    labels = Column(PickleType) 
    features = Column(PickleType) 

這裏的testset代碼:

from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy import Column, String, PickleType, Integer, MetaData 

Base = declarative_base() 
metadata = MetaData() 


class TestSet(Base): 
    __tablename__ = 'test set' 
    id = Column(Integer, primary_key=True) 
    real_id = Column(String(60)) 
    path = Column(String(120)) 
    features = Column(PickleType) 

因此,如果用戶創建時通過train_set=TrueDataSet ins我想創建一個使用TrainSet模型的數據庫,否則創建一個TestSet數據庫。我希望在prepopulate方法中發生這種情況,但是,我不明白該怎麼做 - 文檔調用了這個:Base.metadata.create_all(engine),但我失去了將代碼放在哪裏。

回答

2

首先保存參數train_set

class DataSet: 
    def __init__(self, path_to_set, path_to_db, train_set=False, path_to_labels=None, label_dict=None, 
       custom_name=None): 
     self._train_set = train_set 
     # ... 

然後,在prepopulate使用它來創建正確的模型(S):

def prepopulate(self): 
    engine = create_engine('sqlite:////' + self.__dbpath) 
    if self._train_set: 
     trainset.Base.create_all(engine) 
    else: 
     testset.Base.create_all(engine) 
    self.__prepopulated = True 

一兩件事:不要前綴你的「私人」變量帶雙下劃線。請參閱PEP 8 -- Style Guide for Python Code以供參考。

+0

太好了,謝謝!我只需要將'testset.Base.create_all(引擎)'改成'testset.Base.metadata.create_all(引擎)'(同樣適用於'train set'),但它現在都可以工作。 此外,由於我將編寫很多查詢內容的函數,因此將引擎存儲在類實例中是一個好主意嗎? (而不是在每個類方法中創建它)? –

+1

我不會在任何模型類中存儲引擎,因爲您會將錯誤的東西混合在一起,並會以一種更奇怪的方式將所有東西混合在一起(*模型*不應該知道有關*連接的任何信息*)。相反,在類方法中使用['object_session(self)'](http://docs.sqlalchemy.org/en/rel_0_9/orm/session.html#sqlalchemy.orm.session.object_session)來獲取會話( a-la'transaction')並根據需要查詢其他數據。 – van