[Grok-dev] implements() works, alsoProvides() breaks
Brandon Craig Rhodes
brandon at rhodesmill.org
Thu Aug 30 01:04:47 EDT 2007
I have solved the problems mentioned in the second half of my recent
email, but have encountered more serious problems. And this time, I
can provide very simple example code to show the failing test case!
My last email asked why Grok does not allow me to wrap "normal"
objects (that might come from a database or object library) in
grok.Views, instead of restricting me to using grok.Model instances.
I asked the question because:
- When I created a traverse() method that returns a grok.Model, I
could provide an 'index' View for the object and see the view
render when I visited the object's URL.
- But when traverse() returned a normal object, visiting its URL
returned only a Zope "not available" message, despite the fact that
an 'index' View was available.
I concluded that traversing the plain objects simply did not work.
And I was wrong! The problem was that I was omitting the view name,
and expecting 'index' to be chosen automatically; but the default only
works for grok.Model and grok.Container! In other words:
/myapp/Model_object/index ... worked
/myapp/Model_object ... worked
/myapp/Plain_object/index ... worked
/myapp/Plain_object ... broke completely :-)
The solution was to introduce the following code into my application,
assuming that the class I am trying to View instead of a grok.Model is
class "Plain":
zope.component.provideAdapter('index',
adapts=(Plain, IBrowserRequest),
provides=IDefaultViewName)
I swiped this code from the bootstrap() code of grok._grok, where it
is run twice to provide a default View name of 'index' to grok.Model
and grok.Container. Oh: and it only seems to work if my class
implements the interface IContained. But I can live with that.
And now for my new problem!
I have now found (don't ask how many experiments it took until I
determined this!) that running provideAdapter() this way on one of my
own classes only results in a truly functioning default View name if
my *class itself* provides IContained, but does *not* work if it is
only the object *instance* returned by traverse() that provides
IContained!
This is terribly disappointing, because my actual plan had been to
write traverse() methods that returned arbitrary objects, and that
used alsoProvides() to slap an IContained interface decorator on each
object before returning it to the framework.
This is deeply mystifying to me; my impression from The Book had been
that Zope 3 would treat as equivalent (at least for these purposes)
the three above methods for declaring that an instance provides an
interface.
To test this:
* Create a grokproject; I named mine "Plain".
* Enter the project and create three new templates, perhaps with:
cat > src/plain/app_templates/workingindex.pt <<-EOT
<html><body>Works!</body></html>
EOT
cat > src/plain/app_templates/workingindex2.pt <<-EOT
<html><body>Works too!</body></html>
EOT
cat > src/plain/app_templates/brokenindex.pt <<-EOT
<html><body>Call Brandon if this works without /index!</body></html>
EOT
* Install in ./src/plain/ the "app.py" file attached below.
* Start the server with "bin/zopectl fg".
* Using the Grok UI, create an instance of your app named "a".
* You will find that the following three URLs work fine.
/a/working/index
/a/working2/index
/a/broken/index
* But you will find that only the first two of these URLs work:
/a/working (works)
/a/working2 (works)
/a/broken (broken!)
Thanks to anyone who can help me resolve this mystery! It occurs to
me that this may belong in a bug tracker somewhere, but, right now, I
must sleep. :-)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: app.py
Type: text/x-python
Size: 1503 bytes
Desc: not available
Url : http://mail.zope.org/pipermail/grok-dev/attachments/20070830/4ae5c266/app-0001.py
-------------- next part --------------
--
Brandon Craig Rhodes brandon at rhodesmill.org http://rhodesmill.org/brandon
More information about the Grok-dev
mailing list