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