2017-04-12 51 views
1

我有兩個獨立的SQLAlchemy接口到Postgres數據庫。第一個界面,在燒瓶中應用的背景下,包含此模型:Python SQLAlchemy:反映數據庫中斷/默認/ onupdate方法?

app = create_app() # sets the SQLAlchemy Database URI, etc. 
db = SQLAlchemy(app) 

class User(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow) 
    updated_at = db.Column(db.DateTime, onupdate=datetime.datetime.utcnow) 
    name = db.Column(db.String, nullable=False) 

第二個接口是不通過瓶 - 相反,這是一個偵聽特定事件的腳本,在這種情況下是指執行一些計算並更新數據庫中的一行。要做到這一點,我有SQLAlchemy的反映現存的數據庫:

from sqlalchemy import create_engine, MetaData, Table 
from sqlalchemy.orm import mapper, sessionmaker 
from sqlalchemy.ext.automap import automap_base 
from os import environ 

dbPath = "postgresql://" + ... 
engine = create_engine(dbPath) 

Base = automap_base() 
Base.prepare(engine, reflect=True) 

metadata = MetaData(engine) 

class User(object): 
    pass 

users = Table('user', metadata, autoload=True, autoload_with=engine) 
mapper(User, users) 

Session = sessionmaker(bind=engine) 
session = Session() 

我現在運行到的問題是這樣的:當我使用的第一界面創建新條目或更新一個,工作的事情如預計,並且created_atupdated_at字段被適當地更新。

但是,當我使用第二個界面 - 導入代碼並使用session.query(User)獲取條目並更新它時,updated_at字段不會更改。此外,當我使用此界面創建新用戶時,它會按預期創建新行,但它不填充created_atupdated_at字段。

我的問題:

  1. 這究竟是爲什麼?爲什麼反射似乎打破了default/onupdate方法?
  2. 我該如何解決這個問題?
+0

儘管腳本與燒瓶應用程序沒有任何關係,您也可以在燒瓶中重新使用用戶模型的定義。 – stamaimer

+0

@stamaimer是不錯的形式?這種方法似乎會產生技術債務。 – Newb

+0

你聽了什麼事? [event](http://docs.sqlalchemy.org/en/latest/core/event.html)是否符合您的要求? – stamaimer

回答

2

defaultonupdate在Python中完全由客戶端處理,因此不能反映到數據庫中。請參閱"Limitations of Reflection"。在default情況下,你可以使用server_default

class User(db.Model): 
    ... 
    created_at = db.Column(db.DateTime, 
          server_default=text("now() at time zone 'UTC'")) 

onupdate你必須寫一個數據庫觸發器和使用server_onupdate=FetchedValue()

另一方面,您可以避免所有這些,只需將您的模型從應用程序代碼分離到一個模塊,供Flask應用程序和腳本使用。這當然會更復雜一些,因爲你必須使用vanilla SQLAlchemy聲明而不是Flask-SQLAlchemy的自定義db.Model庫。或者,您可以使用Flask的custom commands來實現您的腳本,這將允許使用Flask-SQLAlchemy擴展。