2013-07-24 40 views
9

我使用Flask作爲我的python wsgi服務器,sqlalchemy作爲我所有的數據庫訪問權限。使用flask-sqlalchemy沒有子類聲明基礎

認爲我想用砂箱的SQLAlchemy擴展在我的應用程序,但我不希望使用聲明的基類(db.Model),相反,我想要使用SQLAlchemy的基礎。 ext.declarative。

這是否破壞了使用擴展的全部目的?


我的使用情況:

我想擴展幫我管理會話/引擎更好一點,但我想單獨處理所有車型。

我其實不會介意使用擴展名,但我想寫嚴格模型。我正在從一個非燒瓶應用程序移植代碼,並且我會隨時推出更改回該項目。如果flask-sqlalchemy允許我在表元數據上作弊,那麼當代碼被推回時會導致問題。我的代碼還有一些部分會執行大量的類型檢查(多態身份),並且我還記得在使用擴展時不推薦使用Table上的類型檢查。

回答

1

SQLAlchemy本身實際上建議你使用Flask包裝器(db.Model)作爲Flask項目。這就是說,我已經在我的Flask項目中使用了declarative_base模型,它更有意義。

它從flask-sqlalchemy中擊敗了SQLAlchemy類的整個目的。

下面是一些示例代碼:

from sqlalchemy import * 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import relationship, sessionmaker 
import datetime 

#set up sqlalchemy 
engine = create_engine('postgresql://<username>:<password>@localhost/flask_database') 
Base = declarative_base() 
metadata = Base.metadata 
metadata.bind = engine 
Session = sessionmaker(bind=engine, autoflush=True) 
session = Session() 


class User(Base): 
    __tablename__ = 'user' 
    id = Column(Integer, primary_key=True) 
    api_owner_id = Column(Integer, ForeignKey('api.id')) 
    email = Column(String(120), unique=True) 
    username = Column(String(120), unique=True) 
    first_name = Column(String(120)) 
    last_name = Column(String(120)) 
    business_name = Column(String(120)) 
    account_type = Column(String(60)) 
    mobile_phone = Column(String(120)) 
    street = Column(String(120)) 
    street2 = Column(String(120)) 
    city = Column(String(120)) 
    state = Column(String(120)) 
    zip_code = Column(String(120)) 
    country = Column(String(120)) 
    creation_date = Column(DateTime, default=datetime.datetime.now()) 
    password = Column(String(120)) 
    #github stuffs 
    github_link = Column(Boolean, default=False) 
    github_usn = Column(String(120)) 
    github_oauth_token = Column(String(160)) 
    #balanced stuffs 
    balanced_account_uri = Column(String(120)) 
    ach_verified = Column(Boolean, default=False) 
    active = Column(Boolean, default=True) 
    profile_updated = Column(Boolean, default=False) 
    account_balance = Column(Numeric(precision=10, scale=2), default=0.00) 
    admin = Column(Boolean, default=False) 
    devapp = relationship('DevApp', backref="user", lazy="dynamic") 
    projects = relationship('Project', backref="user", lazy="dynamic") 
    proposals = relationship('Proposal', backref="user", lazy="dynamic") 
    transactions = relationship('Monies', backref="user", lazy="dynamic") 

    def __repr__(self): 
     return self.email 
+0

您的會話/引擎位有助於說明您的答案。所以,在我的燒瓶應用程序中,我需要傳遞會話以供使用。每次使用後,我是否需要以任何方式清理會話? (也許使用** app.do_teardown_xxx **?) – user2097818

+0

在sessionmaker中使用autoflush = True參數不需要清理。 user = User(email =「[email protected]」) session.add(user) session.commit() –

+0

我不打算在多個線程中運行此操作,但我將使用離散模塊每個使用他們自己的新會話。我打算通過會議制定者。這些模塊將進行逐步更新。提交每個會話實例後,是否應該有任何理由擔心數據完整性? (假設我的承諾不會互相打破)。 – user2097818

7

你可以有瓶,SQLAlchemy的暴露你自己的基本模式,而不是它內置的一個。只是子類SQLAlchemy並覆蓋make_declarative_base

from flask.ext.sqlalchemy import SQLAlchemy 


class CustomAlchemy(SQLAlchemy): 
    def make_declarative_base(self): 
     base = declarative_base(...) 
     ... 
     return base 

db = CustomAlchemy() 
1

實際上,我使用SQLAlchemy的燒瓶中不使用聲明的基礎和我沒有任何問題。如果你願意,你可以隨時這樣做,沒有義務使用對象關係映射器,ORM只是sqlalchemy的一部分。您始終可以使用鍊金術SQL表達式語言,在模型對象中定義您的表格,並定義一些將使用表達式語言的方法。我有這樣的代碼(Model是我之前定義的對象),connect是一個連接到db的裝飾器,它對我來說工作正常。

def connect(func): 
    eng = create_engine(app.config["DATABASE"]) 
    @wraps(func) 
    def wrapped(*args,**kwargs): 
     with closing(eng.connect()) as con: 
      result = con.execute(func(*args,**kwargs)) 
     return result 
    return wrapped 

class User_(Model): 
    def __init__(self): 
     Model.__init__(self) 
     self.metadata = MetaData() 
     self.structure = Table("users", self.metadata, 
           Column("id",Integer,primary_key=True), 
           Column("username",VARCHAR(64)), 
           Column("password",TEXT), 
           Column("email",VARCHAR(100)), 
           Column("about_me",TEXT), 
           Column("deadline",DATETIME), 
           Column("points",INTEGER)), 
           Column("date_created",DATETIME)) 

    @connect 
    def get_hashed_pass(self,username): 
     """ """ 
     t = self.structure 
     s = select([t.c.password]).where(t.c.username == str(username)) 
     return s 
#other methods follow 

Flask's documentation concerning alchemy明確地說,這是完全沒關係做到這一點:

如果你只是想使用數據庫系統(和SQL)抽象層,你基本上只需要發動機

PS哦,還有一件事,他們在文檔中說,如果你想快速入門,你最好使用擴展名,但我個人不太確定,如果你像我一樣,而且你感覺更熟悉用sql查詢而不用ORM,可以讓你快速入門而不需要擴展。

+0

花了我一段時間才明白你的意思(我沒有看到連接裝飾器的方法)。在模型中使用會話將成爲我的下一個問題! – user2097818