【问题标题】:Updating row in SqlAlchemy ORM更新 SqlAlchemy ORM 中的行
【发布时间】:2013-01-15 03:35:49
【问题描述】:

我正在尝试从数据库中获取一行,修改该行并再次保存。
一切都使用 SqlAlchemy

我的代码

from sqlalchemy import Column, DateTime, Integer, String, Table, MetaData
from sqlalchemy.orm import mapper
from sqlalchemy import create_engine, orm

metadata = MetaData()

product = Table('product', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String(1024), nullable=False, unique=True),

)

class Product(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name

mapper(Product, product)


db = create_engine('sqlite:////' + db_path)
sm = orm.sessionmaker(bind=db, autoflush=True, autocommit=True, expire_on_commit=True)
session = orm.scoped_session(sm)

result = session.execute("select * from product where id = :id", {'id': 1}, mapper=Product)
prod = result.fetchone() #there are many products in db so query is ok

prod.name = 'test' #<- here I got AttributeError: 'RowProxy' object has no attribute 'name'

session .add(prod)
session .flush()

不幸的是它不起作用,因为我正在尝试修改 RowProxy 对象。如何以 SqlAlchemy ORM 方式做我想要的(加载、更改和保存(更新)行)?

【问题讨论】:

  • 快速浏览注意:您不会将对象添加到会话中进行修改。您在创建新行时添加。通常,您只需修改代理对象,然后在会话对象上提交。此外,如果您真的想使用 ORM,您通常不会在 SQL 中构造查询并使用 execute 方法。使用查询生成器。
  • 他说他在修改 RowProxy 对象时遇到了 AttributeError。你为什么希望它起作用?

标签: python sqlalchemy


【解决方案1】:

我假设您的意图是使用Object-Relational API。 因此,要更新 db 中的行,您需要通过从表记录中加载映射对象并更新对象的属性来执行此操作。

请参见下面的代码示例。 请注意,我添加了用于创建新映射对象并在表中创建第一条记录的示例代码,最后还有用于删除记录的注释代码。

from sqlalchemy import Column, DateTime, Integer, String, Table, MetaData
from sqlalchemy.orm import mapper
from sqlalchemy import create_engine, orm

metadata = MetaData()

product = Table('product', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String(1024), nullable=False, unique=True),

)

class Product(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name
    def __repr__(self):
        return "%s(%r,%r)" % (self.__class__.name,self.id,self.name)

mapper(Product, product)


db = create_engine('sqlite:////temp/test123.db')
metadata.create_all(db)

sm = orm.sessionmaker(bind=db, autoflush=True, autocommit=True, expire_on_commit=True)
session = orm.scoped_session(sm)

#create new Product record:
if session.query(Product).filter(Product.id==1).count()==0:

    new_prod = Product("1","Product1")
    print "Creating new product: %r" % new_prod
    session.add(new_prod)
    session.flush()
else:
    print "product with id 1 already exists: %r" % session.query(Product).filter(Product.id==1).one()

print "loading Product with id=1"
prod = session.query(Product).filter(Product.id==1).one()
print "current name: %s" % prod.name
prod.name = "new name"

print prod


prod.name = 'test'

session.add(prod)
session.flush()

print prod

#session.delete(prod)
#session.flush()

PS SQLAlchemy 还提供SQL Expression API,允许直接使用表记录而不创建映射对象。在我的实践中,我们在大多数应用程序中都使用 Object-Relation API,有时当我们需要高效地执行低级数据库操作(例如通过一次查询插入或更新数千条记录)时,我们会使用 SQL 表达式 API。

SQLAlchemy 文档的直接链接:

【讨论】:

  • 是使用 ORM 的唯一选择吗?或者是否也可以使用 SQLAlchemy 表达式语言?
猜你喜欢
  • 2018-05-23
  • 2022-08-24
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 1970-01-01
相关资源
最近更新 更多