简体   繁体   English

使用flask-sqlalchemy而没有子类声明基础

[英]using flask-sqlalchemy without the subclassed declarative base

I am using Flask for my python wsgi server, and sqlalchemy for all my database access. 我正在使用Flask作为我的python wsgi服务器,而sqlalchemy使用我的所有数据库访问。

I think I would like to use the Flask-Sqlalchemy extension in my application, but I do not want to use the declarative base class (db.Model), instead, I want to use the base from sqlalchemy.ext.declarative. 我想在我的应用程序中使用Flask-Sqlalchemy扩展,但我不想使用声明性基类(db.Model),而是想要使用sqlalchemy.ext.declarative中的基类。

Does this defeat the entire purpose of using the extension? 这是否会破坏使用扩展程序的全部目的?


My use case: 我的用例:

I would like the extension to help me manage sessions/engines a little better, but I would like to handle all models separately. 我想扩展程序可以帮助我更好地管理会话/引擎,但我想分别处理所有模型。

I actually wouldn't mind using the extension, but I want to write strict models. 我实际上不介意使用扩展,但我想编写严格的模型。 I am porting code from a non-flask application, and I will be pushing changes back to that project as I go. 我正在从一个非烧瓶应用程序移植代码,我会在我去的时候将更改推回到该项目。 If flask-sqlalchemy allows me to cheat on Table metadata for instance, that is going to cause problems when the code is pushed back out. 例如,如果flask-sqlalchemy允许我欺骗表元数据 ,那么当代码被推回时会导致问题。 There are also portions of my code that do lots of type checking (polymorphic identities), and I also remember reading that type checking on Table is not recommended when using the extension. 我的代码中还有一些代码可以进行大量的类型检查(多态身份),我还记得在使用扩展时不建议读取表格上的类型检查。

You can have Flask-SQLAlchemy expose your own base Model instead of it's built-in one. 你可以让Flask-SQLAlchemy公开你自己的基础模型而不是它的内置模型。 Just subclass SQLAlchemy and override make_declarative_base . 只需将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()

SQLAlchemy themselves actually recommend you use the Flask wrapper (db.Model) for Flask projects. SQLAlchemy本身实际上建议您使用Flask包装器(db.Model)进行Flask项目。 That being said I have used the declarative_base model in several of my Flask projects where it made more sense. 话虽如此,我在我的几个Flask项目中使用了declarative_base模型,它更有意义。

It does defeat the whole purpose of the SQLAlchemy class from flask-sqlalchemy. 它确实从flask-sqlalchemy中击败了SQLAlchemy类的整个目的。

Here's some sample code: 这是一些示例代码:

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

I'm actually using sqlalchemy in flask without using declarative base and I don't have any problems. 我实际上在没有使用声明基础的情况下在烧瓶中使用sqlalchemy而且我没有任何问题。 You can always do that if you want to, there is no obligation to use object relational mapper, ORM is just one part of sqlalchemy. 如果你愿意,你总是可以这样做,没有义务使用对象关系映射器,ORM只是sqlalchemy的一部分。 You can always just stay with alchemy sql expression language, define your tables in model objects, and define some methods there that will use expression language. 您可以随时使用alchemy sql表达式语言,在模型对象中定义表,并在那里定义一些将使用表达式语言的方法。 I have a code like this (Model is the object i defined earlier), connect is a decorator which connects to db, it works fine for me. 我有这样的代码(模型是我之前定义的对象),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 explicitly says that it is completely okay to do that: Flask关于炼金术的文件明确表示完全可以这样做:

If you just want to use the database system (and SQL) abstraction layer you basically only need the engine 如果您只想使用数据库系统(和SQL)抽象层,则基本上只需要引擎

PS Oh, and one more thing, they say in the docs that if you want to get started quickly you're better off using extension, but I'm personally not so sure about that, if you're like me and you feel more familiar with the sql queries rather then with ORM, it may be much easier for you to get started quickly without extension. PS哦,还有一件事,他们在文档中说,如果你想快速入门,你最好使用扩展,但我个人不太确定,如果你像我一样,你感觉更多熟悉sql查询而不是ORM,你可以更容易地在没有扩展的情况下快速入门。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM