11

我将 Flask 用于我的 python wsgi 服务器,并将 sqlalchemy 用于我的所有数据库访问。

我想在我的应用程序中使用 Flask-Sqlalchemy 扩展,但我不想使用声明性基类 (db.Model),而是想使用来自 sqlalchemy.ext.declarative 的基类。

这是否违背了使用扩展的全部目的?


我的用例:

我希望扩展帮助我更好地管理会话/引擎,但我想分别处理所有模型。

我实际上不介意使用扩展,但我想编写严格的模型。我正在从非烧瓶应用程序中移植代码,并且我将在进行时将更改推送回该项目。例如,如果 flask-sqlalchemy 允许我在表元数据上作弊,那么当代码被推出时就会导致问题。我的代码的某些部分也进行了大量类型检查(多态标识),我还记得阅读过在使用扩展时不建议对 Table 进行类型检查。

4

3 回答 3

9

您可以让 Flask-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()
于 2013-07-24T18:49:26.193 回答
1

我实际上在烧瓶中使用 sqlalchemy 而不使用声明性基础,我没有任何问题。如果您愿意,您可以随时这样做,没有义务使用对象关系映射器,ORM 只是 sqlalchemy 的一部分。您始终可以使用 alchemy sql 表达式语言,在模型对象中定义表,并在那里定义一些将使用表达式语言的方法。我有这样的代码(模型是我之前定义的对象),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 关于炼金术的文档明确表示完全可以这样做:

如果您只想使用数据库系统(和 SQL)抽象层,您基本上只需要引擎

PS哦,还有一件事,他们在文档中说,如果您想快速入门,最好使用扩展程序,但我个人对此不太确定,如果您像我一样并且感觉更多熟悉 sql 查询而不是 ORM,您可能更容易快速上手而无需扩展。

于 2013-07-24T19:17:09.420 回答
0

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
于 2013-07-24T18:49:15.120 回答