AW: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
Hi Martin Betreff: [Zope3-Users] Weird behaviour of ViewPageTemplateFile() I just stumbled over something that utterly baffles me and hope someone can point out the absolutely obvious to me. I've got a view defined in a configure.zcml that points to this class: class MyView(BrowserView): def __call__(self): self.pt = ViewPageTemplateFile('empty.pt') data = self.pt() return data That works fine. However, I don't really need pt as instance variable, so I turned it into a local variable: class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') data = pt() return data try this: pt = ViewPageTemplateFile('empty.pt') return pt(self) Regards Roger Ineichen ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') data = pt() return data try this: pt = ViewPageTemplateFile('empty.pt') return pt(self) Nope, same result: AttributeError: 'str' object has no attribute 'other' Cheers, mjl ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
On Thu, Apr 10, 2008 at 03:22:33PM +0200, Martin J. Laubach wrote: That works fine. However, I don't really need pt as instance variable, so I turned it into a local variable: class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') data = pt() return data Well, it's called a *View*PageTemplate for a reason :-) If the file is really empty and you do not need to pass any arguments to it (view, context, request), use a plain PageTemplateFile (zope.pagetemplate.pagetemplatefile.PageTemplateFile). Albertas ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
Well, it's called a *View*PageTemplate for a reason :-) If the file is really empty and you do not need to pass any arguments to it (view, context, request), use a plain PageTemplateFile No, of course it's not empty and it needs the parameters. Nor does the view really look as trivial as the example. That was the minimal test case for the behaviour I could come up with. I still don't understand how the naming / storage of a variable holding the page template can influence the page rendering process. Cheers, mjl ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
On Thu, Apr 10, 2008 at 04:08:43PM +0200, Martin J.Laubach wrote: Well, it's called a *View*PageTemplate for a reason :-) If the file is really empty and you do not need to pass any arguments to it (view, context, request), use a plain PageTemplateFile No, of course it's not empty and it needs the parameters. Nor does the view really look as trivial as the example. That was the minimal test case for the behaviour I could come up with. I still don't understand how the naming / storage of a variable holding the page template can influence the page rendering process. ViewPageTemplate must be in the view's namespace, and it magically fishes out the view, view's context and request, and makes them available in the TAL namespace. Otherwise you would have to pass these arguments by hand. When using PageTemplateFile you would have to pass the args like this: pt = PageTemplateFile(file.pt) result = pt(arg1, arg2, arg3=value, arg4=value) Then the positional args would be available in the TAL namespace as args, and the keyword arguments would be available as options: tal:block define=arg1 python:args[0]; arg2 python:args[1]; arg3 options/arg3; arg4 options/arg4; / Arguably, the keyword arguments are a bit less ugly. HTH, Albertas ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
Hi! On Thu, Apr 10, 2008 at 03:22:33PM +0200, Martin J. Laubach wrote: I just stumbled over something that utterly baffles me and hope someone can point out the absolutely obvious to me. Sure. I've got a view defined in a configure.zcml that points to this class: class MyView(BrowserView): def __call__(self): self.pt = ViewPageTemplateFile('empty.pt') data = self.pt() return data That works fine. I'm actually surprised that this works. The usual way in Zope 3 is class MyView(BrowserView): pt = ViewPageTemplateFile('empty.pt') def __call__(self): data = self.pt() return data which can also be shortened to class MyView(BrowserView): __call__ = ViewPageTemplateFile('empty.pt') However, I don't really need pt as instance variable, so I turned it into a local variable: class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') data = pt() return data And that version throws an exception: Traceback (innermost last): Module ZPublisher.Publish, line 119, in publish Module ZPublisher.mapply, line 88, in mapply Module ZPublisher.Publish, line 42, in call_object Module mjl.example.browser.myform, line 31, in __call__ Module Shared.DC.Scripts.Bindings, line 313, in __call__ Module Shared.DC.Scripts.Bindings, line 348, in _bindAndExec Module Shared.DC.Scripts.Bindings, line 1, in ? Module Shared.DC.Scripts.Bindings, line 293, in _getTraverseSubpath This does not look like Zope 3 to me. AttributeError: 'str' object has no attribute 'other' Okay, I know why the code doesn't work, but I don't know why you get this strange Zope 2 error. I'll answer just the first part. Same if I just do the simpler return ViewPageTemplateFile('empty.pt')() of course. I simply do not understand why, what or who does care how I name my variables or where I put them? Please hit me hard with a cluebat. Twice. You have encountered the magic of Python descriptors. Feel free to skip the detailed explanation if you're in a hurry: ViewPageTemplateFile is a descriptor, which is a fancy way of saying object that has a method named __get__. When you access a descriptor from an instance, Python silently calls __get__ for you, so class MyView(BrowserView): pt = ViewPageTemplateFile('empty.pt') def __call__(self): pt = self.pt() is more or less equivalent to class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') pt = pt.__get__(self, ViewPageTemplateFile) ViewPageTemplateFile.__get__ returns a BoundPageTemplate object (it's a bit like the difference between unbound and bound methods) that knows which view it is bound to and can pass it via the view name to your TALES expressions. Now when you invoke ViewPageTemplateFile's __call__, you have to pass the view as the first argument: class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') return pt(self) but when you invoke BoundPageTemplate.__call__, it knows and provides the view argument itself: class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') bound_pt = pt.__get__(self, ViewPageTemplateFile) return bound_pt() which is more or less the same as class MyView(BrowserView): pt = ViewPageTemplateFile('empty.pt') def __call__(self): bound_pt = self.pt return bound_pt() [End of explanation] So, if you really want to use a local variable instead of a class attribute, pass the view itself as the first argument to __call__ class MyView(BrowserView): def __call__(self): pt = ViewPageTemplateFile('empty.pt') data = pt(self) return data HTH, Marius Gedminas -- Anyone can do any amount of work provided it isn't the work he is supposed to be doing at the moment. -- Robert Benchley signature.asc Description: Digital signature ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
ViewPageTemplate must be in the view's namespace, and it magically fishes out the view, view's context and request, and makes them available in the TAL namespace. Ah, so there _IS_ heavy magic involved here. Thanks for clarifying that, I was already doubting my sanity! Cheers, mjl ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
On Apr 10, 2008, at 10:30 AM, Marius Gedminas wrote: I've got a view defined in a configure.zcml that points to this class: class MyView(BrowserView): def __call__(self): self.pt = ViewPageTemplateFile('empty.pt') data = self.pt() return data That works fine. I'm actually surprised that this works. It works because, unlike regular objects, ExtensionClass instances call descriptors when you get a descriptor as an attribute. This is for backward compatibility with __of__ methods (which become __get__ methods). Jim -- Jim Fulton Zope Corporation ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
ViewPageTemplate must be in the view's namespace, and it magically fishes out the view, view's context and request, and makes them available in the TAL namespace. Ah, so there _IS_ heavy magic involved here. Thanks for clarifying that, I was already doubting my sanity! This is exactly the same magic that methods use. ViewPageTemplateFiles are, like functions, meant to be used as methods and to be bound to instances. Okay, then this leads me to the strong suspicion that what I'm (mis)using ViewPageTemplateFiles for is the wrong way to attack the problem. What I'm doing is something along the lines of class MyView(BrowserView): def __call__(self): pagename = somehow_compute_new_page_name(self.request, self.context) pt = ViewPageTemplateFile(pagename) return pt.__get__(self, self.__class__)() but quite obviously, that's not how it's meant to be used, is it... Perhaps I need a radically different approach? Cheers, mjl ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
On Apr 10, 2008, at 11:46 AM, Martin J.Laubach wrote: ViewPageTemplate must be in the view's namespace, and it magically fishes out the view, view's context and request, and makes them available in the TAL namespace. Ah, so there _IS_ heavy magic involved here. Thanks for clarifying that, I was already doubting my sanity! This is exactly the same magic that methods use. ViewPageTemplateFiles are, like functions, meant to be used as methods and to be bound to instances. Jim -- Jim Fulton Zope Corporation ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
On Thu, Apr 10, 2008 at 2:59 PM, Martin J. Laubach [EMAIL PROTECTED] wrote: Perhaps I need a radically different approach? Sounds like you want PageTemplateFile. -Fred -- Fred L. Drake, Jr. fdrake at gmail.com Chaos is the score upon which reality is written. --Henry Miller ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users
Re: [Zope3-Users] Weird behaviour of ViewPageTemplateFile()
On Apr 10, 2008, at 2:59 PM, Martin J. Laubach wrote: ViewPageTemplate must be in the view's namespace, and it magically fishes out the view, view's context and request, and makes them available in the TAL namespace. Ah, so there _IS_ heavy magic involved here. Thanks for clarifying that, I was already doubting my sanity! This is exactly the same magic that methods use. ViewPageTemplateFiles are, like functions, meant to be used as methods and to be bound to instances. Okay, then this leads me to the strong suspicion that what I'm (mis)using ViewPageTemplateFiles for is the wrong way to attack the problem. What I'm doing is something along the lines of class MyView(BrowserView): def __call__(self): pagename = somehow_compute_new_page_name(self.request, self.context) pt = ViewPageTemplateFile(pagename) return pt.__get__(self, self.__class__)() but quite obviously, that's not how it's meant to be used, is it... Perhaps I need a radically different approach? Need is too strong. You might prefer another approach based on what you now know. :) Fred suggested using a page-template class that doesn't behave as a method. Another option might be to create a bunch of methods and then have your function dispatch to those, depending, of course, on how many there are. Jim -- Jim Fulton Zope Corporation ___ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users