python - SQLAlchemy está enrevesada?
sqlalchemy select (6)
Bueno, SQLAlchemy se divide en diferentes partes, la parte principal principal simplemente maneja la base de datos, transformando las consultas construidas en Python en el lenguaje SQL apropiado para la base de datos subyacente. Luego está el soporte para las sesiones, el orm y la nueva sintaxis declarativa.
Parece que SQLObject (no puedo decirlo con seguridad, no lo he usado en muchos años, y aun así, solo una vez) se salta la mayor parte y hace la parte de ORM de inmediato. Esto a menudo facilita las cosas con datos simples (que en la mayoría de los casos puedes salirte con la tuya), pero SQLAlchemy permite diseños de bases de datos más complejos y se vuelve sucio con el archivo db si realmente lo necesitas.
Esto puede parecer bastante discutible, pero acabo de seguir el tutorial de ORM de SQLAlchemy y terminé con el siguiente código:
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
Esto parece increíblemente complicado para efectivamente una tabla de Hello World, especialmente en comparación con el código SQLObject aproximadamente similar:
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
Entiendo que SQLAlchemy es "más poderoso", pero ese poder parece tener un costo, ¿o me estoy perdiendo algo?
Bueno, hay una cosa que falta: el tutorial que menciona no "construye" un ejemplo completo, los diferentes fragmentos de código no están destinados a ser concatenados en un archivo fuente. Más bien, describen las diferentes formas en que se puede utilizar la biblioteca. No hay necesidad de intentar y hacer lo mismo una y otra vez.
Dejando de lado la parte que realmente usa el orm de su ejemplo, el código podría verse así:
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()
La extensión "declarativa" se encarga de definir la tabla y asignarla a su clase, por lo que no necesita declarar la users_table
usted mismo. La clase de Usuario también permitirá crear instancias con argumentos de palabras clave, como User(name="foo")
, (aunque no argumentos de posición). También agregué el uso de scoped_session, lo que significa que puede usar Session
directamente sin tener que crear una instancia (creará una nueva sesión si no hay una presente en el hilo actual, o reutilizará la existente)
Habiendo usado SQLObject (y solo leí sobre SQLAlchemy), puedo decir que una de las fortalezas de SQLObject es la facilidad y simplicidad con las que puedes hacer las cosas. Además, el grupo de correo electrónico ( https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss ) proporciona una excelente asistencia que le responde las respuestas con bastante rapidez.
Los ejemplos de código que das no son manzanas con manzanas. La versión de SQLAlchemy podría reducirse un poco:
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
También puedes encontrar Elixir más como SQLObject (pero como tampoco lo he usado, es solo una suposición).
No habiendo usado SQLObject en absoluto, no puedo comentar exactamente qué SA hace mejor. Pero he tenido grandes experiencias con SA, especialmente cuando se trata de esquemas heredados complicados del mundo real. Hace un buen trabajo al generar buenas consultas SQL de manera predeterminada, y tiene muchas formas de ajustarlas.
He encontrado que el lanzamiento de ascensor del autor de SQLAlchemy se mantiene bastante bien en la práctica.
Prueba Quick ORM , es aún más simple:
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
El ORM rápido se basa en SQLAlchemy, por lo que podríamos decir que SQLAlchemy podría ser tan simple como SQLObject.
usted dice "enrevesado" ... alguien más podría decir "flexible". A veces lo necesitas, a veces no. ¿No es asombroso que tengas elección?