我试图使用一个自定义集合来“连接”(或关联)两个类,但我没能做到。也许我把SqlAlchemy custom collections的整个概念都弄错了,但让我解释一下我在做什么(看看有没有人能给我一个暗示,或者别的什么)
我有一个父类(你们中的一些人会从其他问题中记得)在其中有几个连接器字段(列表)。其中一个连接器将存储类型为“VR”的Child()类的实例,另一个将存储类型为“CC”的子类。在
对于用于存储子对象的集合,我并不需要持久性,但我需要它是一个特殊的类,这样它将有一些我已经实现的方法,并且需要在那里。这将是“ZepConnector”类(在本例中,我需要使用的是foo()方法)。正如您在下面几行中看到的,我在父对象的addChild1()方法中随机测试它的可用性。在
------------------父级.py-----------------在
from megrok import rdb
from sqlalchemy import Column
from sqlalchemy import and_
from sqlalchemy.orm import relationship
from sqlalchemy.types import Integer
from sqlalchemy.types import String
from mylibraries.database.tests.Child import Child
from mylibraries.database.tests.Tables import testMetadata
from mylibraries.database.tests.ZepConnector import ZepConnector
class Parent(rdb.Model):
rdb.metadata(testMetadata)
rdb.tablename("parents_table")
rdb.tableargs(schema='test2', useexisting=False)
id = Column("id", Integer, primary_key=True, nullable=False, unique=True)
_whateverField1 = Column("whatever_field1", String(16)) #Irrelevant
_whateverField2 = Column("whatever_field2", String(16)) #Irrelevant
child1 = relationship(
"Child",
uselist=True,
primaryjoin=lambda: and_((Parent.id == Child.parent_id), (Child.type == "VR")),
collection_class=ZepConnector("VR")
)
child2 = relationship(
"Child",
uselist=True,
primaryjoin=lambda: and_((Parent.id == Child.parent_id), (Child.type == "CC")),
collection_class=ZepConnector("CC")
)
def __init__(self):
print "Parent __init__"
self._whateverField1 = "Whatever1"
self._whateverField2 = "Whatever2"
self.child1 = ZepConnector("VR")
self.child2 = ZepConnector("CC")
def addChild1(self, child):
if isinstance(child, Child):
print("::addChild1 > Testing .foo method: " + str(self.child1.foo()))
# The line above doesn't really makes much
# but testing the accessibility of the .foo() method.
# As I'll explain later, it doesn't work
self.child1.append(child)
def addChild2(self, child):
if isinstance(child, Child):
self.child2.append(child)
请注意,我用的是美卓克。对于那些不熟悉它的人,请允许我解释一下,它只是一个工具,它将Python类映射到SqlAlchemy映射器本身,并使它在使用Grok framework时更加“程序员友好”。在
我想常规SqlAlchemy中Parent()类的映射类似于:
^{pr2}$但我百分之百。。。呃。。。90%。。。呃。。。70%的人确信使用这个工具并不是我要问的问题(我的意思是:我不认为这会干扰SqlAlchemy自定义集合的事情)
孩子很简单:
———————————————————————————————————————————————————————————————————————————————————————————————————————————————儿童.py--------------------------在
import random
from megrok import rdb
from sqlalchemy import Column
from sqlalchemy import ForeignKey
from sqlalchemy.types import Integer
from sqlalchemy.types import String
from mylibraries.database.tests.Tables import testMetadata
class Child(rdb.Model):
rdb.metadata(testMetadata)
rdb.tablename("children_table")
rdb.tableargs(schema='test2', useexisting=False)
parent_id = Column("parent_id", Integer, ForeignKey("test2.parents_table.id"), primary_key=True)
type = Column("type", String(2), nullable=True, primary_key=True)
hasher = Column("hasher", String(5))
def __init__(self):
self.type = None
self.hasher = self.generateHasher()
def setType(self, typeParameter):
if typeParameter in set(["VR", "CC"]):
self.type = typeParameter
@staticmethod
def generateHasher():
retval = str()
for i in random.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 5):
retval += i
return retval
假设每个子实例都有一个惟一的“hasher”字段,可以用作字典中的键(上面的示例与实际情况相差甚远,但它稍微说明了子实例如何工作以及能够创建测试)
现在是我的自定义连接器。我希望它表现为一个列表或集合(更像集合,尽管我不太在意),但它是一个继承自dict的类
------------------ZepConnector.py--------------------在
from sqlalchemy.orm.collections import collection
class ZepConnector(dict):
__emulates__ = list
def __init__(self, type):
self.type = type
# The 'type' will be "VR" or "CC" and it will be stamped
# on every Child() class added through this ZepConnector
def foo(self):
return True
@collection.appender
def append(self, item):
#Appends a child to itself
if self.foo():
item.setType(self.type)
self[item.hasher] = item
@collection.remover
def remove(self, item):
try:
del self[item.hasher]
except ValueError, e:
print("::remove > Got exception when trying to remove entry=" + str(item.hasher) + ". The exception is: " + str(e))
def extend(self, items):
pass
但我不知道为什么,父类中的“ZepConnector”实例似乎不是“ZepConnector”类型,而是“InstrumentedList”:
在Parent()的addChild1方法中,我尝试测试.foo()方法(应该只打印“True”)时,我得到以下错误:
AttributeError: 'InstrumentedList' object has no attribute 'foo'
显示整个回溯:
Traceback (most recent call last):
File "/home/ae/mytests-cms/grokserver/eggs/zope.publisher-3.12.0-py2.4.egg/zope/publisher/publish.py", line 134, in publish
result = publication.callObject(request, obj)
File "/home/ae/mytests-cms/grokserver/eggs/grok-1.1rc1-py2.4.egg/grok/publication.py", line 89, in callObject
return super(ZopePublicationSansProxy, self).callObject(request, ob)
File "/home/ae/mytests-cms/grokserver/eggs/zope.app.publication-3.10.2-py2.4.egg/zope/app/publication/zopepublication.py", line 205, in callObject
return mapply(ob, request.getPositionalArguments(), request)
File "/home/ae/mytests-cms/grokserver/eggs/zope.publisher-3.12.0-py2.4.egg/zope/publisher/publish.py", line 109, in mapply
return debug_call(obj, args)
File "/home/ae/mytests-cms/grokserver/eggs/zope.publisher-3.12.0-py2.4.egg/zope/publisher/publish.py", line 115, in debug_call
return obj(*args)
File "/home/ae/mytests-cms/grokserver/eggs/grokcore.view-1.13.2-py2.4.egg/grokcore/view/components.py", line 101, in __call__
return mapply(self.render, (), self.request)
File "/home/ae/mytests-cms/grokserver/eggs/zope.publisher-3.12.0-py2.4.egg/zope/publisher/publish.py", line 109, in mapply
return debug_call(obj, args)
File "/home/ae/mytests-cms/grokserver/eggs/zope.publisher-3.12.0-py2.4.egg/zope/publisher/publish.py", line 115, in debug_call
return obj(*args)
File "/home/ae/mytests-cms/grokserver/src/grokserver/app.py", line 1575, in render
mylibraries.database.tests.Test.runWholeTest()
File "/home/ae/mytests-cms/mylibraries/database/tests/Test.py", line 54, in runWholeTest
__test()
File "/home/ae/mytests-cms/mylibraries/database/tests/Test.py", line 35, in __test
parent.addChild1(child)
File "/home/ae/mytests-cms/mylibraries/database/tests/Parent.py", line 54, in addChild1
print("::addChild1 > Testing .foo method: " + str(self.child1.foo()))
AttributeError: 'InstrumentedList' object has no attribute 'foo'
Debug at: http://127.0.0.1:8080/_debug/view/1289342582
很奇怪。。。ZepConnector的init方法已正确执行。。。但当我尝试使用它时,它似乎不是ZepConnector。。。在
我又做了几次测试,但都不成功:
在第二次尝试中,我写道:
class ZepConnector(dict):
__emulates__ = set
但这甚至让事情变得更糟,因为我得到:
TypeError: Incompatible collection type: ZepConnector is not list-like
在第三次(或第二次)尝试中,我想好。。。如果说ZepConnector不是一个列表,那么告诉Parent()不要在关系中使用列表可能会有帮助。。。也许声明collection_类是一个ZepConnector会使yn在关系中成为uselist参数…”
所以我写了:
child1 = relationship(
"Child",
uselist = False,
primaryjoin=lambda: and_((Parent.id == Child.parent_id),(Child.type == "VR")),
collection_class=ZepConnector("VR")
)
但这引发了一个令人毛骨悚然的例外,谈到一个我不应该看到的领域,我不想看到。。。曾经。。。:-D
AttributeError: 'ZepConnector' object has no attribute '_sa_instance_state'
我使用的是Python2.4和SqlAlchemy 0.6.6,以防万一。在
如果有人有任何想法,指导,咨询。。。无论什么。。。我真的很感谢你和我分享。。。呃。。。我们。。。在
提前谢谢你!在
(如果你已经走到了这条线上,你当然应该得到一个“谢谢”,因为你耐心地阅读了这篇巨大的帖子)
明白了。在
我在sqlalchemygoogle小组也问过同样的问题,我得到了答案。在
http://groups.google.com/group/sqlalchemy/msg/5c8fc09a75fd4fa7
引用:
感谢迈克尔·拜尔(以及所有试图帮助的人,即使阅读了这么一篇博文)
相关问题 更多 >
编程相关推荐