コード例 #1
0
class Report(BaseReport, ZenPackable):
    """Report object"""

    __pychecker__ = 'no-override'

    meta_type = 'Report'

    # this is deprecated don't use!!!
    description = ""

    security = ClassSecurityInfo()

    _relations = ZenPackable._relations

    def __init__(self, id, title = None, text=None, content_type='text/html'):
        ZenModelRM.__init__(self, id);
        self._template = ZopePageTemplate(id, text, content_type)
        self.title = title

    def __call__(self, *args, **kwargs):
        """Return our rendered template not our default page
        """
        if not 'args' in kwargs:
            kwargs['args'] = args
        template = self._template.__of__(self)
        path_info = template.REQUEST['PATH_INFO'].replace(' ', '%20')
        if (path_info.startswith('/zport/dmd/Reports') and
                path_info not in template.REQUEST['HTTP_REFERER'] and
                'adapt=false' not in template.REQUEST['QUERY_STRING']):
            url = '/zport/dmd/reports#reporttree:'
            url += path_info.replace('/', '.')
            template.REQUEST['RESPONSE'].redirect(url)
        self.auditRunReport()
        return template.pt_render(extra_context={'options': kwargs})


    def ZScriptHTML_tryForm(self, *args, **kwargs):
        """Test form called from ZMI test tab
        """
        return self.__call__(self, args, kwargs)


    def manage_main(self):
        """Return the ZMI edit page of our template not ourself
        """
        template = self._template.__of__(self)
        return template.pt_editForm()
    pt_editForm = manage_main
    
    
    def pt_editAction(self, REQUEST, title, text, content_type, expand):
        """Send changes to our template instead of ourself"""
        template = self._template.__of__(self)
        return template.pt_editAction(REQUEST,
            title, text, content_type, expand)
コード例 #2
0
ファイル: Report.py プロジェクト: zenoss-ce/zenoss-prodbin
class Report(BaseReport, ZenPackable):
    """Report object"""

    __pychecker__ = 'no-override'

    meta_type = 'Report'

    # this is deprecated don't use!!!
    description = ""

    security = ClassSecurityInfo()

    _relations = ZenPackable._relations

    def __init__(self, id, title=None, text=None, content_type='text/html'):
        ZenModelRM.__init__(self, id)
        self._template = ZopePageTemplate(id, text, content_type)
        self.title = title

    def __call__(self, *args, **kwargs):
        """Return our rendered template not our default page
        """
        if not 'args' in kwargs:
            kwargs['args'] = args
        template = self._template.__of__(self)
        path_info = template.REQUEST['PATH_INFO'].replace(' ', '%20')
        if (path_info.startswith('/zport/dmd/Reports')
                and path_info not in template.REQUEST['HTTP_REFERER']
                and 'adapt=false' not in template.REQUEST['QUERY_STRING']):
            url = '/zport/dmd/reports#reporttree:'
            url += path_info.replace('/', '.')
            template.REQUEST['RESPONSE'].redirect(url)
        self.auditRunReport()
        return template.pt_render(extra_context={'options': kwargs})

    def ZScriptHTML_tryForm(self, *args, **kwargs):
        """Test form called from ZMI test tab
        """
        return self.__call__(self, args, kwargs)

    def manage_main(self):
        """Return the ZMI edit page of our template not ourself
        """
        template = self._template.__of__(self)
        return template.pt_editForm()

    pt_editForm = manage_main

    def pt_editAction(self, REQUEST, title, text, content_type, expand):
        """Send changes to our template instead of ourself"""
        template = self._template.__of__(self)
        return template.pt_editAction(REQUEST, title, text, content_type,
                                      expand)
コード例 #3
0
class HTMLPortlet(LocalPropertyManager, Folder):
    """ """

    meta_type = METATYPE_HTMLPORTLET
    icon = 'misc_/NaayaCore/HTMLPortlet.gif'

    manage_options = (
        ({'label': 'Properties Ex', 'action': 'manage_properties_html'},)
        + (Folder.manage_options[0],)
        + Folder.manage_options[3:]
    )

    def all_meta_types(self, interfaces=None):
        """ """
        y = []
        additional_meta_types = ['Image', 'File']
        for x in Products.meta_types:
            if x['name'] in additional_meta_types:
                y.append(x)
        return y

    security = ClassSecurityInfo()

    title = LocalProperty('title')
    body = LocalProperty('body')

    def __init__(self, id, title, body, portlettype, lang):
        #constructor
        self.id = id
        self._setLocalPropValue('title', lang, title)
        self._setLocalPropValue('body', lang, body)
        self.portlettype = portlettype
        self.template = ZopePageTemplate('', HTML_PORTLET_TEMPLATE, 'text/html')

    def __call__(self, context={}, *args):
        """ """
        if not context.has_key('args'):
            context['args'] = args
        context['skin_files_path'] = self.getLayoutTool().getSkinFilesPath()
        wrappedTemplate = self.template.__of__(self)
        context['here'] = self
        return wrappedTemplate.pt_render(extra_context=context)

    def get_type_label(self):
        #returns the label for the portlet type
        return PORTLETS_TYPES[self.portlettype]

    #zmi actions
    security.declareProtected(view_management_screens, 'manage_properties_html')
    def manage_properties(self, title='', body='', lang=None, REQUEST=None):
        """ """
        if lang is None: lang = self.gl_get_selected_language()
        self._setLocalPropValue('title', lang, title)
        self._setLocalPropValue('body', lang, body)
        self._p_changed = 1
        if REQUEST: REQUEST.RESPONSE.redirect('manage_properties_html?save=ok')

    #zmi pages
    security.declareProtected(view_management_screens, 'manage_properties_html')
    manage_properties_html = PageTemplateFile('zpt/htmlportlet_manage_properties', globals())
コード例 #4
0
    def get_mail_body(self, fields, request, context):
        """Returns the mail-body with footer.
        """

        schema = get_fields(context)
        all_fields = [f for f in fields
                      # TODO
                      # if not (f.isLabel() or f.isFileField()) and not (getattr(self,
                      # 'showAll', True) and f.getServerSide())]
                      if not (INamedFile.providedBy(fields[f])) and not (getattr(self, 'showAll', True) and IFieldExtender(schema[f]).serverSide)
                      ]

        # which fields should we show?
        if getattr(self, 'showAll', True):
            live_fields = all_fields
        else:
            live_fields = [
                f for f in all_fields if f in getattr(self, 'showFields', ())]

        if not getattr(self, 'includeEmpties', True):
            all_fields = live_fields
            live_fields = [f for f in all_fields if fields[f]]
            for f in all_fields:
                value = fields[f]
                if value:
                    live_fields.append(f)

        #bare_fields = [schema[f] for f in live_fields]
        bare_fields = dict([(f, fields[f]) for f in live_fields])
        bodyfield = self.body_pt

        # pass both the bare_fields (fgFields only) and full fields.
        # bare_fields for compatability with older templates,
        # full fields to enable access to htmlValue
        replacer = DollarVarReplacer(fields).sub
        extra = {
            'data': bare_fields,
            'fields': dict([(i, j.title) for i, j in getFieldsInOrder(schema)]),
            'mailer': self,
            'body_pre': self.body_pre and replacer(self.body_pre),
            'body_post': self.body_post and replacer(self.body_post),
            'body_footer': self.body_footer and replacer(self.body_footer),
        }
        template = ZopePageTemplate(self.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        body = template.pt_render(extra_context=extra)

        # if isinstance(body, unicode):
            #body = body.encode("utf-8")

        #keyid = getattr(self, 'gpg_keyid', None)
        #encryption = gpg and keyid

        # if encryption:
            #bodygpg = gpg.encrypt(body, keyid)
            # if bodygpg.strip():
                #body = bodygpg

        return body
コード例 #5
0
        def test_template_translation(self):
            tmpl = ZopePageTemplate(id='test_tmpl')
            tmpl.pt_edit('<p i18n:translate="">Home for'
                              ' <span i18n:name="hours">3</span> hours</p>',
                              'text/html')

            self.assertEqual(tmpl.__of__(self.portal)(),
                             u'<p>Home for <span>3</span> hours</p>\n')
コード例 #6
0
    def get_mail_body(self, unsorted_data, request, context):
        """Returns the mail-body with footer.
        """
        schema = get_schema(context)

        form = DummyFormView(context, request)
        form.schema = schema
        form.prefix = 'form'
        form._update()
        widgets = {name: widget.render() for name, widget in form.w.items()}

        data = filter_fields(self, schema, unsorted_data)

        bodyfield = self.body_pt

        # pass both the bare_fields (fgFields only) and full fields.
        # bare_fields for compatability with older templates,
        # full fields to enable access to htmlValue
        if isinstance(self.body_pre, basestring):
            body_pre = self.body_pre
        else:
            body_pre = self.body_pre.output

        if isinstance(self.body_post, basestring):
            body_post = self.body_post
        else:
            body_post = self.body_post.output

        if isinstance(self.body_footer, basestring):
            body_footer = self.body_footer
        else:
            body_footer = self.body_footer.output

        extra = {
            'data':
            data,
            'fields':
            OrderedDict([(i, j.title) for i, j in getFieldsInOrder(schema)]),
            'widgets':
            widgets,
            'mailer':
            self,
            'body_pre':
            body_pre and lnbr(dollar_replacer(body_pre, data)),
            'body_post':
            body_post and lnbr(dollar_replacer(body_post, data)),
            'body_footer':
            body_footer and lnbr(dollar_replacer(body_footer, data)),
        }
        template = ZopePageTemplate(self.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        return template.pt_render(extra_context=extra)
コード例 #7
0
    def get_mail_body(self, unsorted_data, request, context):
        """Returns the mail-body with footer.
        """
        schema = get_schema(context)

        form = DummyFormView(context, request)
        form.schema = schema
        form.prefix = "form"
        form._update()
        widgets = filter_widgets(self, form.w)
        data = filter_fields(self, schema, unsorted_data)

        bodyfield = self.body_pt

        # pass both the bare_fields (fgFields only) and full fields.
        # bare_fields for compatability with older templates,
        # full fields to enable access to htmlValue
        if isinstance(self.body_pre, six.string_types):
            body_pre = self.body_pre
        else:
            body_pre = self.body_pre.output

        if isinstance(self.body_post, six.string_types):
            body_post = self.body_post
        else:
            body_post = self.body_post.output

        if isinstance(self.body_footer, six.string_types):
            body_footer = self.body_footer
        else:
            body_footer = self.body_footer.output

        extra = {
            "data":
            data,
            "fields":
            OrderedDict([(i, j.title) for i, j in getFieldsInOrder(schema)]),
            "widgets":
            widgets,
            "mailer":
            self,
            "body_pre":
            body_pre and lnbr(dollar_replacer(body_pre, data)),
            "body_post":
            body_post and lnbr(dollar_replacer(body_post, data)),
            "body_footer":
            body_footer and lnbr(dollar_replacer(body_footer, data)),
        }
        template = ZopePageTemplate(self.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        return template.pt_render(extra_context=extra)
コード例 #8
0
    def add_subscriber_in_period(self, context, period, subscriber, form,
                                 data):
        request = self.request
        subscriber.first_name = data.get("first_name")
        subscriber.last_name = data.get("last_name")
        subscriber.email = data.get("email")
        subscriber.number_of_people = int(data.get("number_of_people"))
        subscriber.reindexObject()
        period.reindexObject()

        mailer = get_actions(context).get("mailer")
        if not mailer:
            return

        extra_form = DummyFormView(context, request)
        extra_form.schema = form.schema
        extra_form.prefix = "form"
        extra_form._update()
        subscriber_fields = [x[0] for x in getFieldsInOrder(ISubscriber)]
        subscriber_fields.append("period")

        widgets = filter_widgets(extra_form.widgets, subscriber_fields)
        data = filter_fields(data, extra_form.schema, subscriber_fields)
        bodyfield = mailer.body_pt

        extra = {
            "data":
            data,
            "fields":
            OrderedDict([(i, j.title)
                         for i, j in getFieldsInOrder(extra_form.schema)], ),
            "widgets":
            widgets,
            "mailer":
            mailer,
            "body_pre":
            "",
            "body_post":
            "",
            "body_footer":
            "",
        }
        template = ZopePageTemplate(mailer.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        subscriber.all_informations = RichTextValue(
            template.pt_render(extra_context=extra), )
        subscriber.reindexObject()
コード例 #9
0
    def __call__(self):
        """
        Renders the report.
        """

        if not self.data():
            return self.no_results()

        try:
            tal_context = self._getExpressionContext(
                extra={'view': self, },
                tal=True,
            )

            pt = ZopePageTemplate(id='__collective_googleanalytics__')
            pt.pt_edit(self.report.body, 'text/html')
            return pt.__of__(self.context).pt_render(extra_context=tal_context)
        except Exception:
            logger.exception('Error while rendering %r' % self.report.id)
            error_log = getToolByName(self.context, 'error_log')
            error_log.raising(sys.exc_info())
            return self.error()
コード例 #10
0
    def __call__(self, *args, **kwargs):
        if not checkPermission(self._permission, self.context):
            raise Unauthorized()

        portal_url = getToolByName(self.context, 'portal_url')

        zpt = ZopePageTemplate(self.__name__, text=self._template)
        boundNames = {
            'context': self.context,
            'request': self.request,
            'view': self,
            'portal_url': portal_url(),
            'portal': portal_url.getPortalObject(),
        }
        if self._owner is not None:
            zpt.changeOwnership(self._owner)
        zpt = zpt.__of__(self.context)
        try:
            return zpt._exec(boundNames, args, kwargs)
        except NotFound, e:
            # We don't want 404's for these - they are programming errors
            raise Exception(e)
コード例 #11
0
    def __call__(self, *args, **kwargs):
        if not checkPermission(self._permission, self.context):
            raise Unauthorized()

        portal_url = getToolByName(self.context, 'portal_url')

        zpt = ZopePageTemplate(self.__name__, text=self._template)
        boundNames = {
            'context': self.context,
            'request': self.request,
            'view': self,
            'portal_url': portal_url(),
            'portal': portal_url.getPortalObject(),
        }
        if self._owner is not None:
            zpt.changeOwnership(self._owner)
        zpt = zpt.__of__(self.context)
        try:
            return zpt._exec(boundNames, args, kwargs)
        except NotFound, e:
            # We don't want 404's for these - they are programming errors
            raise Exception(e)
コード例 #12
0
    def __call__(self):
        """
        Renders the report.
        """

        if not self.data():
            return self.no_results()

        try:
            tal_context = self._getExpressionContext(
                extra={'view': self, },
                tal=True,
            )

            pt = ZopePageTemplate(id='__collective_googleanalytics__')
            pt.pt_edit(self.report.body, 'text/html')
            return pt.__of__(self.context).pt_render(extra_context=tal_context)
        except Exception:
            logger.exception('Error while rendering %r' % self.report.id)
            error_log = getToolByName(self.context, 'error_log')
            error_log.raising(sys.exc_info())
            return self.error()
コード例 #13
0
    def get_mail_body(self, unsorted_data, request, context):
        """Returns the mail-body with footer.
        """

        schema = get_schema(context)
        data = OrderedDict(
            [x for x in getFieldsInOrder(schema) if x[0] in unsorted_data]
        )

        data.update(unsorted_data)

        all_data = [
            f for f in data
            # TODO
            # if not (f.isLabel() or f.isFileField()) and not (getattr(self,
            # 'showAll', True) and f.getServerSide())]
            if not (self._is_file_data(data[f])) and not (
                getattr(self, 'showAll', True) and
                IFieldExtender(schema[f]).serverSide
            )
        ]

        # which data should we show?
        if getattr(self, 'showAll', True):
            live_data = all_data
        else:
            showFields = getattr(self, 'showFields', [])
            if showFields is None:
                showFields = []

            live_data = [
                f for f in all_data if f in showFields]

        if not getattr(self, 'includeEmpties', True):
            all_data = live_data
            live_data = [f for f in all_data if data[f]]
            for f in all_data:
                value = data[f]
                if value:
                    live_data.append(f)

        bare_data = OrderedDict([(f, data[f]) for f in live_data])
        bodyfield = self.body_pt

        # pass both the bare_fields (fgFields only) and full fields.
        # bare_fields for compatability with older templates,
        # full fields to enable access to htmlValue
        replacer = DollarVarReplacer(data).sub
        extra = {
            'data': bare_data,
            'fields': OrderedDict([
                (i, j.title)
                for i, j in getFieldsInOrder(schema)
            ]),
            'mailer': self,
            'body_pre': self.body_pre and replacer(self.body_pre),
            'body_post': self.body_post and replacer(self.body_post),
            'body_footer': self.body_footer and replacer(self.body_footer),
        }
        template = ZopePageTemplate(self.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        body = template.pt_render(extra_context=extra)

        # if isinstance(body, unicode):
        # body = body.encode("utf-8")

        # keyid = getattr(self, 'gpg_keyid', None)
        # encryption = gpg and keyid

        # if encryption:
        # bodygpg = gpg.encrypt(body, keyid)
        # if bodygpg.strip():
        # body = bodygpg

        return body
コード例 #14
0
ファイル: _field.py プロジェクト: dtgit/dtedu
 def getDefault(self, instance):
     value = ObjectField.getDefault(self, instance)
     zpt = ZopePageTemplate(self.getName())
     zpt.write(value)
     return zpt.__of__(instance)
コード例 #15
0
ファイル: HTMLPortlet.py プロジェクト: eaudeweb/trunk-eggs
class HTMLPortlet(LocalPropertyManager, Folder):
    """ """

    meta_type = METATYPE_HTMLPORTLET
    icon = 'misc_/NaayaCore/HTMLPortlet.gif'

    manage_options = (({
        'label': 'Properties Ex',
        'action': 'manage_properties_html'
    }, ) + (Folder.manage_options[0], ) + Folder.manage_options[3:])

    def all_meta_types(self, interfaces=None):
        """ """
        y = []
        additional_meta_types = ['Image', 'File']
        for x in Products.meta_types:
            if x['name'] in additional_meta_types:
                y.append(x)
        return y

    security = ClassSecurityInfo()

    title = LocalProperty('title')
    body = LocalProperty('body')

    def __init__(self, id, title, body, portlettype, lang):
        #constructor
        self.id = id
        self._setLocalPropValue('title', lang, title)
        self._setLocalPropValue('body', lang, body)
        self.portlettype = portlettype
        self.template = ZopePageTemplate('', HTML_PORTLET_TEMPLATE,
                                         'text/html')

    def __call__(self, context={}, *args):
        """ """
        if not context.has_key('args'):
            context['args'] = args
        context['skin_files_path'] = self.getLayoutTool().getSkinFilesPath()
        wrappedTemplate = self.template.__of__(self)
        context['here'] = self
        return wrappedTemplate.pt_render(extra_context=context)

    def get_type_label(self):
        #returns the label for the portlet type
        return PORTLETS_TYPES[self.portlettype]

    #zmi actions
    security.declareProtected(view_management_screens,
                              'manage_properties_html')

    def manage_properties(self, title='', body='', lang=None, REQUEST=None):
        """ """
        if lang is None: lang = self.gl_get_selected_language()
        self._setLocalPropValue('title', lang, title)
        self._setLocalPropValue('body', lang, body)
        self._p_changed = 1
        if REQUEST: REQUEST.RESPONSE.redirect('manage_properties_html?save=ok')

    #zmi pages
    security.declareProtected(view_management_screens,
                              'manage_properties_html')
    manage_properties_html = PageTemplateFile(
        'zpt/htmlportlet_manage_properties', globals())
コード例 #16
0
 def _cook_template(self):
     zpt = ZopePageTemplate(self.__name__, text=self._template)
     if self._owner is not None:
         zpt.changeOwnership(self._owner)
     zpt = zpt.__of__(self.context)
     return zpt
コード例 #17
0
    def get_mail_body(self, fields, request, context):
        """Returns the mail-body with footer.
        """

        schema = get_fields(context)
        all_fields = [
            f for f in fields
            # TODO
            # if not (f.isLabel() or f.isFileField()) and not (getattr(self,
            # 'showAll', True) and f.getServerSide())]
            if not (self._is_file_data(fields[f]))
            and not (getattr(self, 'showAll', True)
                     and IFieldExtender(schema[f]).serverSide)
        ]

        # which fields should we show?
        if getattr(self, 'showAll', True):
            live_fields = all_fields
        else:
            showFields = getattr(self, 'showFields', [])
            if showFields is None:
                showFields = []

            live_fields = [f for f in all_fields if f in showFields]

        if not getattr(self, 'includeEmpties', True):
            all_fields = live_fields
            live_fields = [f for f in all_fields if fields[f]]
            for f in all_fields:
                value = fields[f]
                if value:
                    live_fields.append(f)

        # bare_fields = [schema[f] for f in live_fields]
        bare_fields = OrderedDict([(f, fields[f]) for f in live_fields])
        bodyfield = self.body_pt

        # pass both the bare_fields (fgFields only) and full fields.
        # bare_fields for compatability with older templates,
        # full fields to enable access to htmlValue
        replacer = DollarVarReplacer(fields).sub
        extra = {
            'data':
            bare_fields,
            'fields':
            OrderedDict([(i, j.title) for i, j in getFieldsInOrder(schema)]),
            'mailer':
            self,
            'body_pre':
            self.body_pre and replacer(self.body_pre),
            'body_post':
            self.body_post and replacer(self.body_post),
            'body_footer':
            self.body_footer and replacer(self.body_footer),
        }
        template = ZopePageTemplate(self.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        body = template.pt_render(extra_context=extra)

        # if isinstance(body, unicode):
        # body = body.encode("utf-8")

        # keyid = getattr(self, 'gpg_keyid', None)
        # encryption = gpg and keyid

        # if encryption:
        # bodygpg = gpg.encrypt(body, keyid)
        # if bodygpg.strip():
        # body = bodygpg

        return body
コード例 #18
0
ファイル: Feedback.py プロジェクト: eea/Products.Reportek
 def renderFeedbacktext(self):
     pt = ZopePageTemplate(self.id+'_tmp')
     pt.write(self.feedbacktext)
     return pt.__of__(self)()
コード例 #19
0
ファイル: actions.py プロジェクト: FHNW/collective.easyform
    def get_mail_body(self, unsorted_data, request, context):
        """Returns the mail-body with footer.
        """
        schema = get_schema(context)

        form = DummyFormView(context, request)
        form.schema = schema
        form.prefix = 'form'
        form._update()
        widgets = {name: widget.render() for name, widget in form.w.items()}
        data = OrderedDict(
            [x for x in getFieldsInOrder(schema) if x[0] in unsorted_data]
        )

        data.update(unsorted_data)
        all_data = [
            f for f in data
            # TODO
            # if not (f.isLabel() or f.isFileField()) and not (getattr(self,
            # 'showAll', True) and f.getServerSide())]
            if not (self._is_file_data(data[f])) and not (
                getattr(self, 'showAll', True) and
                IFieldExtender(schema[f]).serverSide
            )
        ]

        # which data should we show?
        if getattr(self, 'showAll', True):
            live_data = all_data
        else:
            showFields = getattr(self, 'showFields', [])
            if showFields is None:
                showFields = []

            live_data = [
                f for f in all_data if f in showFields]

        if not getattr(self, 'includeEmpties', True):
            all_data = live_data
            live_data = [f for f in all_data if data[f]]
            for f in all_data:
                value = data[f]
                if value:
                    live_data.append(f)

        bare_data = OrderedDict([(f, data[f]) for f in live_data])
        bodyfield = self.body_pt

        # pass both the bare_fields (fgFields only) and full fields.
        # bare_fields for compatability with older templates,
        # full fields to enable access to htmlValue
        if isinstance(self.body_pre, basestring):
            body_pre = self.body_pre
        else:
            body_pre = self.body_pre.output

        if isinstance(self.body_post, basestring):
            body_post = self.body_post
        else:
            body_post = self.body_post.output

        if isinstance(self.body_footer, basestring):
            body_footer = self.body_footer
        else:
            body_footer = self.body_footer.output

        extra = {
            'data': bare_data,
            'fields': OrderedDict([
                (i, j.title)
                for i, j in getFieldsInOrder(schema)
            ]),
            'widgets': widgets,
            'mailer': self,
            'body_pre': body_pre and lnbr(dollar_replacer(body_pre, data)),
            'body_post': body_post and lnbr(dollar_replacer(body_post, data)),
            'body_footer': body_footer and lnbr(
                dollar_replacer(body_footer, data)),
        }
        template = ZopePageTemplate(self.__name__)
        template.write(bodyfield)
        template = template.__of__(context)
        return template.pt_render(extra_context=extra)