2013-07-24 11 views
9

Sto utilizzando Flask per il mio server wsgi python e sqlalchemy per tutti i miei accessi al database.utilizzo di flask-sqlalchemy senza la base dichiarativa sottoclasse

io penso Vorrei utilizzare l'estensione Flask-SQLAlchemy nella mia richiesta, ma non voglio usare la classe di base dichiarativa (db.Model), invece, voglio usare la base da SQLAlchemy. ext.declarative.

Ciò vanifica l'intero scopo dell'utilizzo dell'estensione?


mio caso d'uso:

vorrei l'estensione per aiutarmi a gestire sessioni/motori un po 'meglio, ma vorrei gestire tutti i modelli separatamente.

In realtà non mi dispiacerebbe usare l'estensione, ma voglio scrivere modelli rigidi. Sto effettuando il porting del codice da un'applicazione non-flask e sposterò le modifiche su quel progetto mentre procedo. Se fiasco-sqlalchemy mi consente di imbrogliare il Table metadata per esempio, questo causerà problemi quando il codice viene respinto. Ci sono anche porzioni del mio codice che fanno un sacco di controllo del tipo (identità polimorfiche), e ricordo anche di aver letto che il controllo del tipo su Tabella non è raccomandato quando si usa l'estensione.

risposta

1

SQLAlchemy consigliano effettivamente di utilizzare il wrapper Flask (db.Model) per i progetti Flask. Detto questo, ho usato il modello dichiarative_base in molti dei miei progetti Flask dove aveva più senso.

Fa fallire l'intero scopo della classe SQLAlchemy da flask-sqlalchemy.

Ecco alcuni esempi di codice:

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

La sessione/bit del motore ha aiutato a illustrare la risposta. Quindi, nella mia app, ho bisogno di passare la sessione per l'utilizzo. Devo pulire la sessione in qualsiasi modo dopo ogni utilizzo? (Forse usando ** app.do_teardown_xxx **?) – user2097818

+0

Con autoflush = True param in sessionmaker non è necessaria alcuna pulizia. utente = Utente (email = "[email protected]") session.add (utente) session.commit() –

+0

Non ho intenzione di eseguirlo su più thread, ma avrò moduli discreti ognuno utilizza la propria nuova sessione. Sto pensando di passare il sessionmaker. Quei moduli faranno aggiornamenti progressivi. Dopo aver commesso ogni istanza di sessione, dovrebbero esserci motivi per preoccuparsi dell'integrità dei dati? (supponendo che i miei commit non si sovrappongano). – user2097818

7

Si può avere Flask-SQLAlchemy esporre la propria base modello, invece di è costruito in uno. Basta sottoclasse SQLAlchemy e sostituisci 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

In realtà sto usando sqlalchemy nel pallone senza utilizzare la base dichiarativa e non ho alcun problema. Puoi sempre farlo se lo desideri, non c'è alcun obbligo di utilizzare il relational mapping degli oggetti, ORM è solo una parte di sqlalchemy. Puoi sempre stare con il linguaggio di espressione alchimico di SQL, definire le tue tabelle in oggetti del modello e definire alcuni metodi che useranno il linguaggio delle espressioni. Ho un codice come questo (Model è l'oggetto che ho definito in precedenza), connect è un decoratore che si connette a db, funziona bene per me.

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 dice esplicitamente che è completamente giusto per farlo:

Se si desidera utilizzare il sistema di database (e SQL) livello di astrazione è fondamentalmente solo bisogno il motore

PS Oh, e un'altra cosa, dicono nei documenti che se vuoi iniziare rapidamente stai meglio usando l'estensione, ma personalmente non ne sono così sicuro, se sei come me e ti senti più familiare con le query SQL piuttosto che con ORM, potrebbe essere molto più semplice iniziare rapidamente senza estensione.

+0

Mi ci è voluto un po 'per capire il significato (non ho visto il decorator Connect sul metodo). Usare una sessione all'interno di una modella sarebbe stata la mia prossima domanda! – user2097818

Problemi correlati