How to pass template text to a view programmatically without using a file?

StackOverflow https://stackoverflow.com/questions/22374551

  •  14-06-2023
  •  | 
  •  

سؤال

I'm writing some tests and I need to use templates in my view without using a file (e.g. via ViewPageTemplateFile). The template must evaluate the tal expressions and access the functions of the view. Here is my current problem. I get an error on evaluating the view in the PageTemplate. I'm not sure whether my code follows best practices.

from plone.app.testing import TEST_USER_NAME, TEST_USER_PASSWORD
from plone.testing.z2 import Browser
from zope.component import getGlobalSiteManager
from zope.publisher.interfaces.browser import IBrowserView
from Products.Five.browser import BrowserView
from zope.pagetemplate.pagetemplate import PageTemplate

class MyView(BrowserView):
    def __init__(self, context, request):
        self.context = context
        self.request = request
    def render(self):
        template = PageTemplate()
        text = '''\
<div tal:on-error="string:view fails"><span tal:replace="view/var"/></div>
<div tal:on-error="string:python fails"><span tal:replace="python:'python works'"/></div>
            '''
        template.write(text)
        return template()
    def __call__(self):
        return self.render()
    def var(self):
        return 'my_value'

global_site_manager = getGlobalSiteManager()
global_site_manager.registerAdapter(MyView, (None, None), IBrowserView, 'my_view')

browser=Browser(app.Plone)
browser.addHeader('Authorization',
                  'Basic %s:%s' % (TEST_USER_NAME, TEST_USER_PASSWORD))
browser.open(app.Plone.absolute_url() + '/@@my_view')
print browser.contents

produces following output:

<div>view fails</div>
<div>
    python works
</div>
هل كانت مفيدة؟

المحلول

My workaround until now is to create my own class MyPageTemplate(PageTemplate), passing the view's instance as argument in the constructor, and override pt_getContext to populate the namespace with view, context, and request from the instance.

I would like to know whether there is a better solution (best practices).

Here my workaround:

from plone.app.testing import TEST_USER_NAME
from plone.app.testing import TEST_USER_PASSWORD
from plone.testing.z2 import Browser
from zope.component import getGlobalSiteManager
from zope.publisher.interfaces.browser import IBrowserView
from Products.Five.browser import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.pagetemplate.pagetemplate import PageTemplate
from zope.interface import Interface
from zope.publisher.browser import IDefaultBrowserLayer

class MyPageTemplate(PageTemplate):
    instance = None
    def __init__(self, instance):
        self.instance = instance
    def pt_getContext(self, instance, request, **kw):
        namespace = super(MyPageTemplate, self).pt_getContext(**kw)
        namespace['view'] = self.instance
        namespace['context'] = self.instance.context
        namespace['request'] = self.instance.request
        return namespace

class MyView(BrowserView):
    def __init__(self, context, request):
        self.context = context
        self.request = request
    def render(self):
        template = MyPageTemplate(self)
        text = '''\
<div tal:on-error="string:request fails">request<span tal:replace="structure request"/> works</div>
<div tal:on-error="string:context fails">context/id=<span tal:replace="context/id"/> works</div>
<div tal:on-error="string:view fails">view/my_var=<span tal:replace="view/my_var"/> works</div>
<div tal:on-error="string:python fails"><span tal:replace="python:'python works'"/></div>
            '''
        template.write(text)
        return template()
    def __call__(self):
        return self.render()
    def my_var(self):
        return 'my_value'

global_site_manager = getGlobalSiteManager()
global_site_manager.registerAdapter(MyView, (None, None), IBrowserView, 'my_view')

browser=Browser(app.Plone)
browser.addHeader('Authorization', 'Basic %s:%s' % (TEST_USER_NAME, TEST_USER_PASSWORD))
browser.open(app.Plone.absolute_url() + '/@@my_view')
print browser.contents
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top