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

Martin Aspeli optilude at gmx.net
Wed Apr 18 20:17:49 UTC 2007


Maurits van Rees wrote:
> Hi Martin,
> 
> Martin Aspeli, on 2007-04-18:
>>> Inherit from object
>>> -------------------
>>>
>>>     class MyView(object):
>>>         def __init__(self, context, request):
>>>             self.context = context
>>>             self.request = request
>>>
>>> The view is not Acquisition wrapped, which means that any permission
>>> you set in the configure.zcml is ignored and everyone can see this
>>> view, right?
>>>
>>> You define your own __init__() so you can handle the context anyway you
>>> please.
>>>
>> This doesn't work in Zope 2. You need to inherit from Acquisition.Explicit
>> at a minimum, or you'll get strange security errors.
> 
> I switched eXtremeManagement browser views from object to Five's
> BrowserView because it is supposedly better.  Diffs are here:
> 
> http://dev.plone.org/collective/changeset/40756
> http://dev.plone.org/collective/changeset/40771
> 
> But it worked fine before those changes.  I did not see security
> errors.  That is on Zope 2.9, Plone 2.5.
> 
> It might depend on what exactly is done in those browser views, but
> the things that my browser views do apparently do not cause strange
> security errors.  Maybe I was just lucky. :)

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. :)

>>> Inherit from Five
>>> -----------------
>>>
>>>     from Products.Five.browser import BrowserView
>>>     class MyView(BrowserView):
>>>
>>> The view is Acquisition wrapped, so Zope security kicks in, which is
>>> probably good.
>>>
>>> If you do not overwrite the __init__() you can use the context with
>>> self.context.
>>>
>> This is the correct approach, imho. However, note that whe you access
>> 'self.context' it will be aq wrapped in the context of the view (since it
>> inherits from Acquisition.Explicit). If self.context is a content item, it
>> also has an inner acquisition chain from its containment. If you do
>> something on the object that needs to e.g. acquire tools or perform explicit
>> security checks, you probably want the inner chain since the outer one
>> contains the view.
> 
> 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:

(pdb) aq_chain(self.context)

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

(pdb) aq_chain(self)

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

> 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.

Martin





More information about the Product-Developers mailing list