2017-07-08 30 views
1

我想在獨立的模塊或類中實現我的數據庫實現。但我正在努力處理一些細節。一個簡單的例子:如何在單獨的模塊中管理peewee數據庫?

from peewee import * 

db = SqliteDatabase(':memory:') 

class BaseModel(Model): 
    class Meta: 
     database = db 

class User(BaseModel): 
    name = CharField() 

db.connect() 
db.create_tables([User,]) 
db.commit() 

@db.atomic() 
def add_user(name): 
    User.create(name=name).save() 

@db.atomic() 
def get_user(name): 
    return User.get(User.name == name) 

到目前爲止這工作正常。我可以在這裏實現我的數據庫接口並將其作爲模塊導入。

現在我希望能夠在運行時選擇數據庫文件。所以我需要一種方法來定義Model類,而不需要定義前面的SqliteDatabase('somefile')。我試圖封裝在一個新的數據庫類,以後我可以從導入和創建一個實例的一切:

from peewee import * 

class Database: 

    def __init__(self, dbfile): 
     self.db = SqliteDatabase(dbfile) 

     class BaseModel(Model): 
      class Meta: 
       database = self.db 

     class User(BaseModel): 
      name = CharField() 

     self.User = User 

     self.db.connect() 
     self.db.create_tables([User,]) 
     self.db.commit() 

    @self.db.atomic() # Error as self is not known on this level 
    def add_user(self, name): 
     self.User.create(name=name).save() 

    @self.db.atomic() # Error as self is not known on this level 
    def get_user(self, name): 
     return self.User.get(self.User.name == name) 

現在我可以打電話例如database = Database('database.db')或選擇其他任何文件名。我甚至可以在同一個程序中使用多個數據庫實例,每個實例都有自己的文件。

但是,有兩個問題的方法:

  • 我還需要定義模型類之前指定的數據庫驅動程序(SqliteDatabase)。爲了解決這個問題,我定義了__init__()方法中的Model類,然後用self.User = User創建一個別名。我不太喜歡這種方法(它只是不覺得整潔的代碼),但至少它是有效的。
  • 我不能使用@db.atomic()修飾器,因爲self在課堂級別是未知的,所以我會在這裏創建一個實例。

所以這個類的方法似乎不工作得很好。有沒有更好的方法來定義模型類,而不必先選擇要存儲數據庫的位置?

回答

4

如果您需要在運行時更改數據庫驅動程序,然後Proxy是很長的路要走

# database.py 
import peewee as pw 

proxy = pw.Proxy() 

class BaseModel(pw.Model): 
    class Meta: 
    database = proxy 

class User(BaseModel): 
    name = pw.CharField() 

def add_user(name): 
    with proxy.atomic() as txn: 
    User.create(name=name).save() 

def get_user(name): 
    with proxy.atomic() as txn: 
    return User.get(User.name == name) 

從現在開始,每次上加載的模塊,它將不需要初始化數據庫。相反,你可以在運行時初始化和如下

# main.py 

import peewee as pw 
import database as db 

sqlite_1 = pw.SqliteDatabase('sqlite_1.db') 
sqlite_2 = pw.PostgresqlDatabase('sqlite_2.db') 

db.proxy.initialize(sqlite_1) 
sqlite_1.create_tables([db.User], safe=True) 
db.add_user(name="Tom") 

db.proxy.initialize(sqlite_2) 
sqlite_2.create_tables([db.User], safe=True) 
db.add_user(name="Jerry") 

多間切換,但如果連接是唯一重要的事情,那麼init()方法就足夠了。

+1

哇,這實際上是記錄,爲什麼我錯過了?如果數據庫驅動程序不變,該文檔還建議使用'[db.init()](http://docs.peewee-orm.com/en/latest/peewee/database.html#deferring-initialization)'。 – Feodoran

+0

@Feodoran謝謝你的補充。更新了答案。 – tarashypka

0

現在我想能夠在運行時選擇數據庫文件。所以我 需要一種方法來定義Model類,而不需要定義 SqliteDatabase('somefile')。我想在一個新的數據庫類,我可以在以後導入到封裝一切 和

Peewee使用元類來定義表的名稱(Model.Meta.db_table)和數據庫(Model.Meta.database

創建 實例

調用一個模型特定代碼之前設置這些屬性(或者創建一個表或到DML語句)

'Allow to define database dynamically'

0

問題:我不能使用@ db.atomic()裝飾,因爲自己不是在類級別稱爲

做到,因爲你self.User做到這一點。
我想知道atomic()而不是atomic,但是你告訴正在正常工作

class Database: 

    def __init__(self, dbfile): 
     self.db = SqliteDatabase(dbfile) 

     ... 
     @self.db.atomic() 
     def __add_user(self, name): 
      self.User.create(name=name).save() 
     self.add_user = __add_user 

     @self.db.atomic() 
     def __get_user(self, name): 
      return self.User.get(self.User.name == name) 
     self.get_user = __get_user 

相關:Define models separately from Database() initialization

相關問題