Browser views: inherit from object or BrowserView from Five/Plone

Maurits van Rees m.van.rees at zestsoftware.nl
Thu Apr 19 09:34:09 UTC 2007


Martin Aspeli, on 2007-04-18:
> Come to think of it, Five's implementation of the <browser:page /> 
> directive injects its BrowserView class as a base class of your class. 
> This is bad voodoo magic, though. It's going to happen. You need it. So 
> be explicit about it. :)

Ouch, so that is why inheriting from object also just works.  Explicit
is better than implicit, so I will indeed inherit from the Five
BrowserView explicitly.

>> So getToolByName(self.context, 'portal_catalog') could go wrong?  It
>> works for me.
>
> It'll work, but it's more subtle than that. To understand what's going 
> on, you need to put a pdb breakpoint in a method in a view, e.g. try:
>
> from Acquisition import aq_chain, aq_inner
> class MyView(BrowserView):
>
>      def __call__(self):
>          import pdb; pdb.set_trace()
>
> Register and invoke this view, and then look at this in PDB:

I will make some notes here, so Google can find my thoughts for me
later. ;-)

All aq_chains below end the same: parent of the context object, then
parent of the parent, etc, until it finds the PloneSite and then the
base Zope App and then they all end with:
  <ZPublisher.BaseRequest.RequestContainer object at ...>

> (pdb) aq_chain(self.context)

This lists the context, then the view, then the context again, then
the parents.  So that is what is happening in probably all my views
currently.  It works, but it could be better I see.

> (pdb) aq_chain(aq_inner(self.context))

This just lists the context and then the parents.  Looks cleanest.  At
least it is the shortest.

> (pdb) aq_chain(self)

This lists the view, then the context, then the parents.  It would
work in most cases I guess, but it seems better to avoid this.

> Bear in mind that when things are being acquired, they walk up the 
> outermost aq chain.

And with aq_inner you tell acquisition to forget about all outer
acquisition chains.  Okay.  It is beginning to get clearer, thanks.

Well, let's print one more test with aq_self while I'm at it.

(Pdb) from Acquisition import aq_inner, aq_self, aq_chain
(Pdb) self
<Products.Five.metaclass.MyProjects object at 0xb31c6ecc>
(Pdb) self.context
<ATDocument at /projects.zestsoftware.nl/front-page>
(Pdb) pp aq_chain(aq_self(self.context))
[<ATDocument at /projects.zestsoftware.nl/front-page>,
 <PloneSite at /projects.zestsoftware.nl>,
 <Application at >,
 <ZPublisher.BaseRequest.RequestContainer object at 0xb56955ec>]
(Pdb) pp aq_chain(aq_self(self))
[<Products.Five.metaclass.MyProjects object at 0xb31c6ecc>]
(Pdb) from Acquisition import aq_base

Oh, and with aq_base:

(Pdb) pp aq_chain(aq_base(self.context))
[<ATDocument at front-page>]
(Pdb) pp aq_chain(aq_base(self))
[<Products.Five.metaclass.MyProjects object at 0xb31c6ecc>]


For those interested and not so knowledgable with this whole
acquisition business (for example myself :)),
Acquisition/interfaces.py is short but instructive.

>> Come to think of it, it also seems to be fine when I do this:
>> 
>>     getToolByName(self, 'portal_catalog')
>> 
>> where self is the View.
>> 
>> Am I overlooking anything?
>
> Your view is wrapped in acquisition. That's why it works. But I consider 
> the statement above bad form and I've had problems with similar things 
> before.

I can imagine that.  Trust me, this code example is not in one of my
views currently, and I will avoid adding it. :)

-- 
Maurits van Rees | http://maurits.vanrees.org/ [NL]
            Work | http://zestsoftware.nl/
"Do not worry about your difficulties in computers,
 I can assure you mine are still greater."





More information about the Product-Developers mailing list