Note: To be fully equivalent to ZCML you should set the index
variable to specify which template you are using. That way the TTW customization will work too.
# foo.py
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.publisher.browser import BrowserPage
class FooView(BrowserPage):
index = ViewPageTemplateFile('foo.pt')
One other pattern you can use with a browser view is adding an update method.
class FooView(BrowserPage):
index = ViewPageTemplateFile('foo.pt')
def __call__(self):
self.update()
return self.index()
def update(self):
self.portal_catalog = ... # initialize code
But this is not the question.
So what is the difference? There is no difference. A browser view must be a callable. The ZCML directive builds this callable in a way the object has an index which must return the rendered page.
But creating the template on each call (your example) there is one difference: you are creating a new instance of the template on each call of the browser view. This is not the case with class variable.
One last option: You don't need a class argument in the directive
<configure xmlns:browser="http://namespaces.zope.org/browser">
<browser:page
…
template="foo.pt"
…
/>
</configure>
For more information, you should read the code of the directive, which uses SimpleViewClass where src is the template name.