2009-05-13 44 views
30

này có thể có vẻ khá tranh cãi, nhưng tôi chỉ đi qua SQLAlchemy của ORM tutorial và kết thúc với đoạn mã sau:SQLAlchemy được phức tạp?

from sqlalchemy import create_engine 
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 

engine = create_engine('sqlite:///:memory:', echo=True) 

metadata = MetaData() 
users_table = Table('users', metadata, 
    Column('id', Integer, primary_key=True), 
    Column('name', String), 
    Column('fullname', String), 
    Column('password', String) 
) 

metadata.create_all(engine) 

Base = declarative_base() 
class User(Base): 
    __tablename__ = 'users' 

    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    fullname = Column(String) 
    password = Column(String) 

    def __init__(self, name, fullname, password): 
     self.name = name 
     self.fullname = fullname 
     self.password = password 

    def __repr__(self): 
     return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password) 

users_table = User.__table__ 
metadata = Base.metadata 

Session = sessionmaker(bind=engine) 
Session = sessionmaker() 
Session.configure(bind=engine) # once engine is available 
session = Session() 

# actually using the ORM isn't too bad.. 
ed_user = User('ed', 'Ed Jones', 'edspassword') 
session.add(ed_user) 

our_user = session.query(User).filter_by(name='ed').first() 
print our_user 

session.add_all([ 
    User('wendy', 'Wendy Williams', 'foobar'), 
    User('mary', 'Mary Contrary', 'xxg527'), 
    User('fred', 'Fred Flinstone', 'blah')]) 

ed_user.password = 'f8s7ccs' 

print session.dirty 
print session.new 
session.commit() 

for instance in session.query(User).order_by(User.id): 
    print instance.name, instance.fullname 

for name, fullname in session.query(User.name, User.fullname): 
    print name, fullname 

Điều này có vẻ vô cùng phức tạp cho hiệu quả một bảng Hello World, đặc biệt là so với các mã SQLObject khoảng tương tự:

from sqlobject import SQLObject, StringCol, sqlhub, connectionForURI 

sqlhub.processConnection = connectionForURI('sqlite:/:memory:') 

class Person(SQLObject): 
    fname = StringCol() 
    mi = StringCol(length=1, default=None) 
    lname = StringCol() 

Person.createTable() 

p = Person(fname="John", lname="Doe") 
p.mi = 'Q' 
p2 = Person.get(1) 
print p2 
print p2 is p 

Tôi hiểu SQLAlchemy là "mạnh hơn", nhưng sức mạnh đó dường như có chi phí hoặc tôi thiếu gì đó?

+8

Điện có tính phí? Bạn đang nói gì vậy –

+12

Sức mạnh của SQLAlchemy có chi phí sử dụng đơn giản? – dbr

+3

Hãy thử Elixir như đã đề cập dưới đây, Hello World của bạn sẽ rất giống với SQLObject và bạn sẽ vẫn có thể truy cập lớp SQLAlchemy. Tôi đã sử dụng SQLObject và đã thất vọng bởi những hạn chế của nó, và tôi rất hài lòng với Elixir cho đến nay (nó thiếu một tài liệu nhỏ và hỗ trợ, nhưng cơ sở người dùng dường như có giới hạn không may). –

Trả lời

85

Vâng, có một điều bạn đang thiếu: hướng dẫn bạn đề cập không "xây dựng" một ví dụ hoàn chỉnh, các đoạn mã khác nhau không có nghĩa là được ghép vào một tệp nguồn. Thay vào đó, chúng mô tả các cách khác nhau mà thư viện có thể được sử dụng. Không cần phải cố gắng và làm điều tương tự hơn và hơn nữa một lần nữa cho mình.

Rời ra thực-sử dụng-the-orm phần từ ví dụ của bạn, mã có thể trông như thế này:

from sqlalchemy import * 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker, scoped_session 

engine = create_engine('sqlite:///:memory:', echo=True) 
Base = declarative_base(bind=engine) 
Session = scoped_session(sessionmaker(engine)) 

class User(Base): 
    __tablename__ = 'users' 

    id = Column(Integer, primary_key=True) 
    name = Column(String) 
    fullname = Column(String) 
    password = Column(String) 

Base.metadata.create_all() 

Tiện ích "tường thuật" chăm sóc định bàn và lập bản đồ nó đến lớp học của bạn , do đó bạn không cần tự khai báo số users_table. Lớp người dùng cũng sẽ cho phép instantiating với các đối số từ khóa, như User(name="foo"), (nhưng không phải là đối số vị trí). Tôi cũng đã thêm scoped_session, điều này có nghĩa là bạn có thể trực tiếp sử dụng Session mà không cần phải khởi tạo nó (nó sẽ khởi tạo một phiên mới nếu chưa có một hiện tại trong chuỗi hiện tại hoặc sử dụng lại hiện tại)

+2

Điều đó có vẻ hợp lý hơn một chút so với mã tôi đã kết thúc. Cảm ơn! – dbr

+1

Tôi rất do dự về việc sử dụng 'scoped_session' cho nhiều thứ; Trừ khi bạn biết lý do tại sao bạn cần lưu trữ cục bộ luồng, bạn nên nhanh chóng thực hiện phiên một cách rõ ràng và vượt qua nó khi cần. – SingleNegationElimination

+1

@TokenMacGuy Tôi không đồng ý hoàn toàn. 'scoped_session' lấy tất cả các đối số phỏng đoán và không cần thiết đi qua việc sử dụng các phiên. Bạn chỉ cần xác định lớp 'scoped_session' của bạn lúc bắt đầu, sau đó khởi tạo nó ở bất cứ nơi nào bạn cần truy cập vào phiên làm việc và hệ thống sẽ thực hiện phần còn lại. Tôi đã tìm thấy nó cực kỳ tiện dụng cho tất cả các ứng dụng web mà tôi đã viết. – CoreDumpError

0

bạn nói "phức tạp" .... ai đó khác có thể nói "linh hoạt". Đôi khi bạn cần nó đôi khi bạn không. Không phải là nó tuyệt vời mà bạn có một sự lựa chọn?

+0

Chắc chắn, nhưng tôi nói "phức tạp" bởi vì nó dường như buộc bạn phải sử dụng rất nhiều tính năng của nó để làm những thứ cơ bản. Tính linh hoạt là tuyệt vời, nhưng không phải nếu nó liên quan đến năm dòng nhập khẩu chỉ để bắt đầu! – dbr

1

Vâng, SQLAlchemy được chia thành các phần khác nhau, phần lõi chính chỉ xử lý DB, chuyển các truy vấn được xây dựng python của bạn sang ngôn ngữ SQL thích hợp cho DB cơ bản. Sau đó, có hỗ trợ cho các phiên, orm và cú pháp khai báo mới.

Có vẻ như SQLObject (Tôi không thể nói chắc chắn, đã không sử dụng nó trong nhiều năm, và thậm chí sau đó, chỉ một lần) bỏ qua phần lớn và thực hiện phần ORM ngay lập tức. Điều này thường làm cho mọi thứ trở nên dễ dàng hơn cho dữ liệu đơn giản (mà bạn có thể loại bỏ trong hầu hết các trường hợp), nhưng SQLAlchemy cho phép bố cục db phức tạp hơn, và giảm xuống và dơ bẩn với db nếu bạn thực sự cần nó.

+0

SQLObject dường như hỗ trợ nhiều thứ nâng cao hơn, như mối quan hệ một-nhiều/nhiều-một/nhiều-nhiều (bao gồm mọi bố cục cơ sở dữ liệu tôi đã thấy) và các giao dịch. – dbr

10

Ví dụ mã mà bạn cung cấp không phải là táo-to-táo. Phiên bản SQLAlchemy thể pared xuống một chút:

from sqlalchemy import create_engine 
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey 
from sqlalchemy.ext.declarative import declarative_base 
from sqlalchemy.orm import sessionmaker 

engine = create_engine('sqlite:///:memory:', echo=True) 
Base = declarative_base() 

class User(Base): 
    __tablename__ = 'users' 

    id = Column('id', Integer, primary_key=True) 
    name = Column('name', String) 
    fullname = Column('fullname', String) 
    password = Column('password', String) 

    def __repr__(self): 
     return "" % (self.name, self.fullname, self.password) 

Base.metadata.create_all(engine) 

Session = sessionmaker(bind=engine) 
session = Session() 

# actually using the ORM isn't too bad.. 
ed_user = User(name='ed', fullname='Ed Jones', password='edspassword') 
session.add(ed_user) 

our_user = session.query(User).filter_by(name='ed').first() 

session.add_all([ 
    User(name='wendy', fullname='Wendy Williams', password='foobar'), 
    User(name='mary', fullname='Mary Contrary', password='xxg527'), 
    User(name='fred', fullname='Fred Flinstone', password='blah')]) 

ed_user.password = 'f8s7ccs' 

session.flush() 

for instance in session.query(User).order_by(User.id): 
    print instance.name, instance.fullname 

for name, fullname in session.query(User.name, User.fullname): 
    print name, fullname 

Bạn cũng có thể tìm thấy Elixir giống như SQLObject (nhưng kể từ khi tôi đã không sử dụng một trong hai, đó chỉ là một phỏng đoán).

Không sử dụng SQLObject chút nào, tôi không thể nhận xét chính xác SA nào tốt hơn. Nhưng tôi đã có những trải nghiệm tuyệt vời với SA, đặc biệt là khi giao dịch với các lược đồ di sản, phức tạp, thực tế phức tạp. Nó làm một công việc tốt để tìm ra các truy vấn SQL tốt theo mặc định, và có rất nhiều cách để điều chỉnh chúng.

Tôi đã tìm thấy SQLAlchemy author's elevator pitch để giữ khá tốt trong thực tế.

1

Đã sử dụng SQLObject (và chỉ đọc về SQLAlchemy), tôi có thể nói rằng một trong những điểm mạnh của SQLObject là sự dễ dàng và đơn giản mà bạn có thể hoàn thành công việc.Ngoài ra, hỗ trợ tuyệt vời được cung cấp bởi nhóm email (https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss) sẽ nhận được câu trả lời nhanh chóng cho bạn.

1

Hãy thử Quick ORM, nó thậm chí còn đơn giản hơn:

from quick_orm.core import Database 
from sqlalchemy import Column, String 

class User(object): 
    __metaclass__ = Database.DefaultMeta 
    name = Column(String(30)) 

if __name__ == '__main__': 
    database = Database('sqlite://') 
    database.create_tables() 

    user = User(name = 'Hello World') 
    database.session.add_then_commit(user) 

    user = database.session.query(User).get(1) 
    print 'My name is', user.name 

Quick ORM được xây dựng dựa SQLAlchemy, vì vậy chúng tôi có thể nói rằng SQLAlchemy có thể đơn giản như SQLObject.

+0

Tôi xin lỗi vì quick_orm không được duy trì nữa. –

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