2013-07-24 26 views
9

Tôi đang sử dụng Flask cho máy chủ wsgi python của tôi và sqlalchemy cho tất cả truy cập cơ sở dữ liệu của tôi.sử dụng bình phương sqlalchemy mà không có cơ sở khai báo lớp con

I nghĩ Tôi muốn sử dụng phần mở rộng Flask-Sqlalchemy trong ứng dụng của mình, nhưng tôi không muốn sử dụng lớp cơ sở khai báo (db.Model), thay vào đó, tôi muốn sử dụng cơ sở từ sqlalchemy. ext.declarative.

Điều này có đánh bại toàn bộ mục đích của việc sử dụng tiện ích không?


trường hợp sử dụng của tôi:

Tôi muốn mở rộng để giúp tôi quản lý phiên/động cơ tốt hơn một chút, nhưng tôi muốn để xử lý tất cả các mô hình riêng biệt.

Tôi thực sự không bận tâm khi sử dụng tiện ích, nhưng tôi muốn viết mô hình nghiêm ngặt. Tôi đang chuyển mã từ một ứng dụng không bình, và tôi sẽ đẩy các thay đổi trở lại dự án đó khi tôi đi. Nếu bình phương sqlalchemy cho phép tôi lừa trên Bảng siêu dữ liệu chẳng hạn, điều đó sẽ gây ra sự cố khi mã bị đẩy lùi ra ngoài. Ngoài ra còn có các phần của mã của tôi mà làm rất nhiều loại kiểm tra (nhận dạng đa hình), và tôi cũng nhớ đọc rằng loại kiểm tra trên Bảng không được khuyến khích khi sử dụng phần mở rộng.

Trả lời

1

SQLAlchemy thực sự khuyên bạn nên sử dụng Flask wrapper (db.Model) cho các dự án Flask. Điều đó đang được nói rằng tôi đã sử dụng mô hình declarative_base trong một số dự án Flask của tôi, nơi nó có ý nghĩa hơn.

Nó đánh bại toàn bộ mục đích của lớp SQLAlchemy từ bình phương sqlalchemy.

Dưới đây là một số mẫu mã:

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

Phiên/bit động cơ của bạn đã giúp minh họa câu trả lời của bạn. Vì vậy, trong ứng dụng bình của tôi, tôi cần phải vượt qua phiên để sử dụng. Tôi có cần dọn dẹp phiên này theo bất kỳ cách nào sau mỗi lần sử dụng không? (Có thể sử dụng ** app.do_teardown_xxx **?) – user2097818

+0

Với autoflush = True param trong sessionmaker không cần dọn dẹp. người dùng = Người dùng (email = "[email protected]") phiên.add (người dùng) session.commit() –

+0

Tôi không có kế hoạch để chạy điều này trên nhiều chủ đề, nhưng tôi sẽ có các mô-đun rời rạc mỗi người sử dụng phiên mới của riêng họ. Tôi đang lên kế hoạch để vượt qua các phiên làm việc. Những mô-đun sẽ thực hiện cập nhật liên tục. Sau khi cam kết mỗi phiên phiên, có nên có lý do gì để lo lắng về tính toàn vẹn của dữ liệu không? (giả sử các cam kết của tôi không clobber lẫn nhau). – user2097818

7

Bạn có thể có Flask-SQLAlchemy phơi bày cơ sở mẫu riêng của bạn thay vì nó được xây dựng trong một. Chỉ cần phân lớp SQLAlchemy và ghi đè 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

Tôi đang sử dụng sqlalchemy trong bình mà không sử dụng cơ sở khai báo và tôi không gặp bất kỳ sự cố nào. Bạn luôn có thể làm điều đó nếu bạn muốn, không có nghĩa vụ phải sử dụng bản đồ quan hệ đối tượng, ORM chỉ là một phần của sqlalchemy. Bạn luôn có thể ở lại với ngôn ngữ biểu thức thuật toán giả kim, xác định các bảng của bạn trong các đối tượng mô hình và xác định một số phương thức ở đó sẽ sử dụng ngôn ngữ biểu thức. Tôi có một mã như thế này (Mô hình là đối tượng tôi đã xác định trước đó), kết nối là một trang trí kết nối với db, nó hoạt động tốt cho tôi.

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 dứt khoát nói rằng nó hoàn toàn không quan trọng để thực hiện điều đó:

Nếu bạn chỉ muốn sử dụng hệ thống cơ sở dữ liệu (và SQL) lớp trừu tượng về cơ bản bạn chỉ cần động cơ

PS Oh, và một điều nữa, họ nói trong tài liệu rằng nếu bạn muốn bắt đầu một cách nhanh chóng, bạn nên sử dụng phần mở rộng, nhưng cá nhân tôi không chắc chắn về điều đó, nếu bạn giống tôi và bạn cảm thấy quen thuộc hơn với các truy vấn sql thay vì sau đó với ORM, bạn có thể dễ dàng bắt đầu nhanh hơn mà không cần mở rộng.

+0

Tôi mất một lúc để hiểu ý nghĩa của bạn (Tôi không thấy trình trang trí kết nối trên phương thức). Sử dụng một phiên bên trong một mô hình sẽ là câu hỏi tiếp theo của tôi! – user2097818

Các vấn đề liên quan