2012-03-17 22 views
1

我有一個多年來一直使用的python模塊來處理一系列工作文本文件。我現在需要將某些信息存儲在數據庫中(使用SQLAlchemy),但我仍然希望在不使用數據庫支持的情況下使用該模塊的靈活性,即不必實際具有sqlalchemy import(或已安裝)。截至目前,我有以下...我一直在創建ProductDBProduct等取決於我打算使用數據庫或不。在運行時添加數據庫支持

from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 

class Product(object): 
    pass 

class WebSession(Product): 
    pass 

class Malware(WebSession): 
    pass 

class DBProduct(Product, Base): 
    pass 

class DBWebSession(WebSession, DBProduct): 
    pass 

class DBMalware(Malware, DBWebSession): 
    pass 

但是,我覺得有一個更簡單/更清潔的方式來做到這一點。我覺得我正在創造一個繼承混亂和潛在的問題。理想情況下,我想創建一個ProductWebSessionWebSession等類(也許使用裝飾器),其中包含使用數據庫的必要信息,但它只能在調用類似enable_db_support()之後啓用/功能。一旦這個函數被調用,那麼無論我創建什麼對象,它本身(以及它繼承的所有對象)都會啓用所有列的綁定等。我還應該注意,如果我以某種方式找出如何將ProductDBProduct包含在一個類,我有時需要2個版本的相同功能:1如果啓用了db支持,則調用1,如果不支持則爲1。當enable_db_support()被調用時,我也考慮過「重新創建」對象層次結構,但是結果也是一場噩夢。

任何幫助表示讚賞。

回答

0

那麼,你可能會通過使用Classical Mapping而不使用declarative擴展名來創建純粹的非數據庫感知模型。在這種情況下,但是,您將無法使用relationships,因爲它們是在SA中使用,但對於簡單的數據導入/導出類型的模型,這應該足夠了:

# models.py 
class User(object): 
    pass 

---- 

# mappings.py 
from sqlalchemy import Table, MetaData, Column, ForeignKey, Integer, String 
from sqlalchemy.orm import mapper 
from models import User 

metadata = MetaData() 

user = Table('user', metadata, 
      Column('id', Integer, primary_key=True), 
      Column('name', String(50)), 
      Column('fullname', String(50)), 
      Column('password', String(12)) 
     ) 

mapper(User, user) 

另一種選擇是將有一個在其他模塊中定義的模型的基類,在啓動該基類時,它可以是DB感知的,或者在DB感知版本的情況下,添加關係和引擎配置等附加功能...

+0

感謝您的回覆。這可能對我有用。我只需要研究關係問題。我傾向於依賴「關係」,但它仍然有效。謝謝。 – redlamb 2012-03-19 01:39:37

+0

我越想到它,我想我會考慮採用這種方法,但並不是因爲需要在數據庫中存儲信息時潛在地覆蓋某些類的已定義函數。你知道是否有可能(或者我會如何去做)使用這種方法重新定義班級的某些功能?再次感謝。 – redlamb 2012-03-19 02:09:02

+0

@redlamb:好吧,由於強大的python的強大功能,只需將方法分配給類,就可以在「enable_db_support()」中添加關係:'DBProduct.versions = relationship('ProductVersion',...) '。以同樣的方式,你可以重寫方法:你只需定義一個新的(非綁定)方法,比如'def db_override_me(self,param1,...):...'然後(重新)將它分配給你class:'DBProduct .override_me = db_override_me'。雖然我擔心這種類型的設計可能會有更好的解決方案...... – van 2012-03-19 07:13:06

0

在我看來DRYest要做的事情就是抽象出你的數據存儲格式的細節,不管是純文本文件還是數據庫。

也就是說,寫一些代碼用來存儲數據的抽象層,使得抽象層的輸出可以在SQL或文本之間切換。

或者換句話說,不要寫ProductDB_Product類。相反,寫一個store_data()函數可以告訴使用format='text'format='db'。然後隨處使用。

這實際上是SQLAlchemy在幕後做的同樣的事情 - 您不必爲SQLAlchemy編寫單獨的代碼,這取決於它是否驅動mySQL,PostgreSQL等。這些都是在SQLAlchemy中處理的,並且您使用抽象(數據庫中立)界面。


或者,如果你反對SQLAlchemy的是,它不是一個Python的內置,總是有sqlite3。這給你一個SQL關係數據庫的所有優點,而不需要任何胖子。


或者交替使用sqlite3作爲中間格式。因此,重寫全部您的代碼使用sqlite3,然後根據需要從sqlite3轉換爲純文本(或其他數據庫)。在極限情況下,轉換爲純文本只有一個sqlite3 db .dump away.

+0

'store_data()'方法是可能的,但是我會失去'SQLAlchemy'提供的「無縫性」。此外,我將不得不記住調用該函數,並可能有另一個用於更新。我沒有反對使用SQLAlchemy,實際上,這就是我在使數據持久化一個數據庫。但是,有很多情況我(或同事)不需要將數據保存在數據庫中。在這些情況下,我寧願SQLAlchemy(或數據庫驅動程序)不是必需的安裝/導入。 – redlamb 2012-03-19 01:36:55