[Zope3-Users] sqlos - getting factory of NoneType
Christian Lück
christian.lueck at ruhr-uni-bochum.de
Wed Jan 4 14:25:37 EST 2006
>> But when I`m trying to add an
>>
>> <browser:addMenuItem
>> class="test.main.Person"
>> title="Person"
>> description="Person objects"
>> view="addperson.html"
>> permission="zope.ManageContent"
>> />
>>
>> tag to my configure.zcml - zapi.getFactories() returns me factory of
>> NoneType (with name something like "BrowserAdd__test.main.Person"
>
> No, the above code looks fine. The created factory name seems also ok.
>
>> Without mentioned addMenuItem tag - everything is OK.
>
> Okay, so we call those configuration directives.
>
>> So, the question is - how can i define "proper" factory?
>
> You can create a factory using the <factory> directive by itself or inside the
> <content> directive. There are plenty examples out there describing this.
>
Hi
The problem with sqlos seems: It does only work if ONE AND ONLY ONE
factory for the content component (interface) in question is registered.
And this one-and-only factory has to be registered with the
zcml-directive in a special sqlos namespace, ie.
<sqlos:factory
id="quotationtool.BookSQLObject"
component=".book.Book"
title="BookSQLObject"
description="A book object for the sql resourcedb."
/>
When a second factory is registered for the same interface, ie.
<factory
id="quotationtool.BookWithInitialValues"
component=".book.BookFactory"
title="BookWithInitialValues"
description="A factory for book object with initial values."
/>
sqlos fails to get the objects stored on the database (you get blank
browser pages).
The reason seems to be the implementation of
sqlos.container.SQLObjectContainer, which maps between sql-unique-keys
(SQLObject-names) and zope-object-names. The mapping mechanism makes use
of the factory.
further analysis:
>>> from zope.app.debug import Debugger
>>> debugger = Debugger('var/Data.fs', 'etc/site.zcml')
[snip]
>>> root = debugger.root()
My SQLObjectContainer is on the root folder an its name is 'resources':
>>> resources = root['resources']
>>> resources
<quotationtool.resourcedb.resourcedb.ResourceDB object at 0xb6e2002c>
Now lets check the registered factories:
We yust do the same like in the allowedFactories() method of
sqlos.container.SQLObjectContainer (first step to map the names)
>>> from zope.app import zapi
>>> from sqlos.interfaces import ISQLObject
>>> from zope.app.container.constraints import checkFactory
>>> for name, factory in zapi.getFactoriesFor(ISQLObject,
context=resources):
... print "Name: %s ; Factory: %s" % (name, factory)
... if checkFactory(resources, None, factory):
... print "checkedOK"
...
Name: quotationtool.BookWithInitialValues ; Factory:
<quotationtool.resourcedb.book.BookFactory object at 0xb602236c>
checkedOK
Name: quotationtool.BookSQLObject ; Factory: <SQLObjectFactory for
<class 'quotationtool.resourcedb.book.Book'>>
checkedOK
*PROBLEM:* the non-sqlos factory certainly is not able do do any name
mapping. You see it, when you try do get the keys or items in the container:
>>> for key in resources.keys(): print key
...
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File
"/var/lib/zope3.1/instance/zope.test-3.2.0.b2.local/lib/python/sqlos/container.py",
line 93, in keys
for name, obj in self.items(): yield name
File
"/var/lib/zope3.1/instance/zope.test-3.2.0.b2.local/lib/python/sqlos/container.py",
line 109, in items
factory = zapi.getUtility(IISQLObject, factoryName, context=self)
File
"/usr/local/src/Zope-3.2.0b2/build/lib.linux-i686-2.4/zope/component/__init__.py",
line 257, in getUtility
raise ComponentLookupError(interface, name)
zope.component.interfaces.ComponentLookupError: (<InterfaceClass
sqlos.interfaces.IISQLObject>, u'quotationtool.BookWithInitialValues')
maybe *SOLUTIONS*:
1) I tried a marker-interface which I called ISQLObjectFactory to
excpilitely mark the content class as the yust factory. Then I changed
the allowedFactories() method:
if ISQLObjectFactory.providedBy(factory): yield factory
But I didn't come along that way :(
2) I overwrote the allowedFactories() method in the implementation of
the container. I am really not happy with it, because checking for a
specific factory-name is not the style things should be wired together
in zope (not as elegant as 1) ).
class ResourceDB(SQLObjectContainer):
"""A ResourceDB object is the base-container for Books etc."""
implements(IResourceDB)
def allowedFactories(self):
for name, factory in zapi.getFactoriesFor(ISQLObject, context=self):
if name == "quotationtool.BookSQLObject":
if checkFactory(self, None, factory):
yield name
This way it works, I see the sql-objects and can even edit them :) - But
works yust to run into the next bigger problem... (I can't create
objects due to rollback problems) :((((
*FACIT*:
sqlos really *****!
Regards
Christian
More information about the Zope3-users
mailing list