- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用 SQLAlchemy将我的对象存储在数据库中的版本。为此,我有一个 save(...)
函数:
#!/usr/bin/env python
# encoding: utf-8
from sqlalchemy import Column, Integer, MetaData, String, Table, create_engine
from sqlalchemy.orm import mapper, sessionmaker
class MyClass(object):
def __init__(self, title):
self.title = title
def __str__(self):
return '%s' % (self.title)
def save(object_list):
metadata = MetaData()
my_class_table = Table('my_class',
metadata,
Column('id', Integer, primary_key=True),
Column('title', String(255), nullable=False))
# everything is OK here, output:
# some title
# another title
# yet another title
for obj in object_list:
print obj
mapper(MyClass, my_class_table)
# on Linux / SQLAlchemy 0.6.8, this fails with
# Traceback (most recent call last):
# File "./test.py", line 64, in <module>
# save(my_objects)
# File "./test.py", line 57, in save
# print obj
# File "./test.py", line 11, in __str__
# return '%s' % (self.title)
# File "/usr/lib/python2.7/dist-packages/sqlalchemy/orm/attributes.py", line 167, in __get__
# return self.impl.get(instance_state(instance),
# AttributeError: 'NoneType' object has no attribute 'get'
# on Mac OSX / SQLAlchemy 0.7.5, this fails with
# Traceback (most recent call last):
# File "./test.py", line 64, in <module>
# save(my_objects)
# File "./test.py", line 57, in save
# print obj
# File "./test.py", line 11, in __str__
# return '%s' % (self.title)
# File "/Library/Python/2.7/site-packages/sqlalchemy/orm/attributes.py", line 165, in __get__
# if self._supports_population and self.key in dict_:
# File "/Library/Python/2.7/site-packages/sqlalchemy/orm/attributes.py", line 139, in __getattr__
# key)
# AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' object has an attribute '_supports_population'
for obj in object_list:
print obj
# (more code to set up engine and session...)
if __name__ == '__main__':
my_objects = [MyClass('some title'), MyClass('another title'), MyClass('yet another title')]
save(my_objects)
在我看来,当我创建映射器时,映射器隐式地对我的对象做了一些事情,我不能再使用它们了。从我读到的in similar questions ,这并非完全未知。
这种行为是预期的吗?
我在这里有什么基本错误吗?
映射和存储我的对象的正确方法是什么?
附加信息:我在 Mac OSX 10.7.3 Lion 上使用 SQLAlchemy 0.7.5 和系统默认的 Python 2.7.1,在 Kubuntu 11.10 虚拟机上使用 SQLAlchemy 0.6.8 和系统默认的 Python 2.7.2+。
更新:SQLAlchemy 映射器似乎是 well known to change objects到“SQLAlchemy 需要”。链接文章中的解决方案是在调用 mapper(...)
之后创建对象。
虽然我已经有了有效的对象 - 但我不能再使用它们了...< br/>
如何让 SQLAlchemy 存储我的对象?
更新 2:我的印象是我误解了一些关于 ORM 的基本知识:
我认为 SQLAlchemy 映射器概念为我提供了一种方法来定义我的对象并在我的应用程序中使用它们与任何数据库分离 - 只有当我想持久化它们时,我才引入 SQLAlchemy 并让它完成映射 a 的所有繁重工作类对象到数据库表。此外,除了持久性函数 save(...)
和 load(...)
.
但是,通过查看下面的第一个响应,我了解到在使用任何对象之前我必须将类映射到数据库表;这将是在我的程序的最开始。也许我在这里弄错了,但这似乎是 SQLAlchemy 的一个非常严格的设计限制——所有的松散耦合都消失了。考虑到这一点,我也没有看到首先使用映射器的好处,因为我想要的“后期耦合”在 SQLAlchemy 中在技术上似乎是不可能的,我不妨只做这种“声明式”并混合和将业务逻辑与持久性代码混合:-(
更新 3:我回到第一个问题,再次阅读 SQLAlchemy。它在 front page 上说对了:
SQLAlchemy is most famous for its object-relational mapper (ORM), an optional component that provides the data mapper pattern, where classes can be mapped to the database in open ended, multiple ways - allowing the object model and database schema to develop in a cleanly decoupled way from the beginning.
然而,根据我迄今为止的经验,SQLAlchemy 似乎根本没有兑现这一 promise ,因为它迫使我从一开始就将对象模型和数据库模式结合起来。毕竟我听说过 SQLAlchemy,我真的很难相信情况确实如此,我宁愿假设我还没有理解一些基本的东西。
我做错了什么?
更新 4:
为了完整起见,我想在创建任何业务对象之前添加完成所有映射的工作示例代码:
#!/usr/bin/env python
# encoding: utf-8
from sqlalchemy import Column, Integer, MetaData, String, Table, create_engine
from sqlalchemy.orm import mapper, sessionmaker
class MyClass(object):
def __init__(self, title):
self.title = title
def __str__(self):
return '%s' % (self.title)
def save(object_list, metadata):
engine = create_engine('sqlite:///:memory:')
metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
for obj in object_list:
try:
session.add(obj)
session.commit()
except Exception as e:
print e
session.rollback()
# query objects to test they're in there
all_objs = session.query(MyClass).all()
for obj in all_objs:
print 'object id :', obj.id
print 'object title:', obj.title
if __name__ == '__main__':
metadata = MetaData()
my_class_table = Table('my_class',
metadata,
Column('id', Integer, primary_key=True),
Column('title', String(255), nullable=False))
mapper(MyClass, my_class_table)
my_objects = [MyClass('some title'), MyClass('another title'), MyClass('yet another title')]
save(my_objects, metadata)
在我自己的(非示例)代码中,我从它自己的模块中导入 MyClass
并在单独的“对象存储库”类中进行映射,该类在中创建 MetaData
它的 __init__(...)
方法并将其存储在成员中,因此 save(...)
和 load(...)
持久性方法可以根据需要访问它。所有主要应用程序需要做的就是在一开始就创建存储库对象;这包含了 SQLAlchemy 对一个类设计的影响,而且还将业务对象和映射表定义分布到代码中的不同位置。还不确定我是否会长期坚持下去,但目前看来还行。
对像我这样的 SQLAlchemy 新手的最后快速提示:你必须始终使用同一个元数据对象,否则你会得到像 no such table
或 class not mapped
这样的异常.
最佳答案
SQLAlchemy 绝对会修改映射的类。 SQLAlchemy 将此称为工具。
观察:
>>> print(MyClass.__dict__)
{'__module__': '__main__', '__str__': <function __str__ at 0x106d50398>, '__dict__':
<attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of
'MyClass' objects>, '__doc__': None, '__init__': <function __init__ at 0x106d4b848>}
>>> mapper(MyClass, my_class_table)
Mapper|MyClass|my_class
>>> print(MyClass.__dict__)
{'__module__': '__main__', '_sa_class_manager': <ClassManager of <class
'__main__.MyClass'> at 7febea6a7f40>, 'title':
<sqlalchemy.orm.attributes.InstrumentedAttribute object at 0x10fba4f90>, '__str__':
<function __str__ at 0x10fbab398>, 'id': <sqlalchemy.orm.attributes.InstrumentedAttribute
object at 0x10fba4e90>, '__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None, '__init__':
<function __init__ at 0x10fbab410>}
同样,普通 MyClass
实例和经过检测的 MyClass
实例之间也存在差异:
>>> prem = MyClass('premapper')
>>> mapper(MyClass, my_class_table)
Mapper|MyClass|my_class
>>> postm = MyClass('postmapper')
>>> print prem
{'title': 'premapper'}
>>> print postm
{'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at 0x10e5b6d50>, 'title': 'postmapper'}
您的 NoneType
错误是因为现在检测的 MyClass.title
(已替换为 InstrumentedAttribute
描述符)正在尝试获取_sa_instance_state
属性通过 instance_state(instance)
。 _sa_instance_state
由对象创建时经过检测的 MyClass
创建,而不是由未检测的 MyClass
创建。
仪器是必不可少的。这样做是为了使用描述符将属性访问、分配和其他重要的对象状态更改传达给映射器。 (例如,如何在不修改类以监视对象中的属性访问的情况下延迟列加载甚至集合访问?)MyClass
对象未绑定(bind)到表,但它们确实需要绑定(bind)到映射器。您可以在不更改域对象的代码 的情况下更改映射选项和表,但不一定更改您的域对象本身。 (毕竟,您可以将单个对象连接到多个映射器和多个表。)
将检测视为以主题-观察者模式透明地将“主题”实现添加到“观察者”映射器的映射类。显然,您不能在任意对象上实现主体-观察者模式——您需要使被观察对象符合 Subject 接口(interface)。
我想可以通过为它创建一个 _sa_instance_state
对象来就地检测一个实例(我不知道如何——我必须阅读 mapper( )
代码),但我不明白为什么这是必要的。如果您的对象有可能被 SQLAlchemy 持久化,那么在创建该对象的任何实例之前,只需为该持久性定义映射和表。您不需要创建引擎或 session ,也不需要任何数据库来定义映射。
使用完全未检测的应用程序对象甚至可以逃脱的唯一方法是,如果您的用例非常微不足道,类似于 pickle
或 unpickle
听写。例如,如果没有检测,您永远无法在集合属性中加载或保存相关对象。你真的不打算这样做吗?如果是这样,也许你会更高兴根本不使用 sqlalchemy.orm
而只使用底层 Expression API持久化您的实例?
关于python - SQLAlchemy:映射器是否更改了我的对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9535001/
我有一个 if 语句,如下所示 if (not(fullpath.lower().endswith(".pdf")) or not (fullpath.lower().endswith(tup
然而,在 PHP 中,可以: only appears if $foo is true. only appears if $foo is false. 在 Javascript 中,能否在一个脚
XML有很多好处。它既是机器可读的,也是人类可读的,它具有标准化的格式,并且用途广泛。 它也有一些缺点。它是冗长的,不是传输大量数据的非常有效的方法。 XML最有用的方面之一是模式语言。使用模式,您可
由于长期使用 SQL2000,我并没有真正深入了解公用表表达式。 我给出的答案here (#4025380)和 here (#4018793)违背了潮流,因为他们没有使用 CTE。 我很欣赏它们对于递
我有一个应用程序: void deleteObj(id){ MyObj obj = getObjById(id); if (obj == null) { throw n
我的代码如下。可能我以类似的方式多次使用它,即简单地说,我正在以这种方式管理 session 和事务: List users= null; try{ sess
在开发J2EE Web应用程序时,我通常会按以下方式组织我的包结构 com.jameselsey.. 控制器-控制器/操作转到此处 服务-事务服务类,由控制器调用 域-应用程序使用的我的域类/对象 D
这更多是出于好奇而不是任何重要问题,但我只是想知道 memmove 中的以下片段文档: Copying takes place as if an intermediate buffer were us
路径压缩涉及将根指定为路径上每个节点的新父节点——这可能会降低根的等级,并可能降低路径上所有节点的等级。有办法解决这个问题吗?有必要处理这个吗?或者,也许可以将等级视为树高的上限而不是确切的高度? 谢
我有两个类,A 和 B。A 是 B 的父类,我有一个函数接收指向 A 类型类的指针,检查它是否也是 B 类型,如果是将调用另一个函数,该函数接受一个指向类型 B 的类的指针。当函数调用另一个函数时,我
有没有办法让 valgrind 使用多个处理器? 我正在使用 valgrind 的 callgrind 进行一些瓶颈分析,并注意到我的应用程序中的资源使用行为与在 valgrind/callgrind
假设我们要使用 ReaderT [(a,b)]超过 Maybe monad,然后我们想在列表中进行查找。 现在,一个简单且不常见的方法是: 第一种可能性 find a = ReaderT (looku
我的代码似乎有问题。我需要说的是: if ( $('html').attr('lang').val() == 'fr-FR' ) { // do this } else { // do
根据this文章(2018 年 4 月)AKS 在可用性集中运行时能够跨故障域智能放置 Pod,但尚不考虑更新域。很快就会使用更新域将 Pod 放入 AKS 中吗? 最佳答案 当您设置集群时,它已经自
course | section | type comart2 : bsit201 : lec comart2 :
我正在开发自己的 SDK,而这又依赖于某些第 3 方 SDK。例如 - OkHttp。 我应该将 OkHttp 添加到我的 build.gradle 中,还是让我的 SDK 用户包含它?在这种情况下,
随着 Rust 越来越充实,我对它的兴趣开始激起。我喜欢它支持代数数据类型,尤其是那些匹配的事实,但是对其他功能习语有什么想法吗? 例如标准库中是否有标准过滤器/映射/归约函数的集合,更重要的是,您能
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 9 年前。 Improve
我一直在研究 PHP 中的对象。我见过的所有示例甚至在它们自己的对象上都使用了对象构造函数。 PHP 会强制您这样做吗?如果是,为什么? 例如: firstname = $firstname;
...比关联数组? 关联数组会占用更多内存吗? $arr = array(1, 1, 1); $arr[10] = 1; $arr[] = 1; // <- index is 11; does the
我是一名优秀的程序员,十分优秀!