Beispiel #1
0
    def render(self, slots_filled=None, *args, **kwargs):
        slots_filled = slots_filled or []
        context_args_variables = getfullargspec(self.context).args[1:]
        context_args = {
            key: kwargs[key]
            for key in context_args_variables if key in kwargs
        }
        context = self.context(**context_args)
        template = get_template(self.template(context))
        slots_in_template = self.slots_in_template(template)

        if slots_in_template:
            valid_slot_names = set([slot.name for slot in slots_in_template])
            nodelist = NodeList()
            for node in template.template.nodelist:
                if (node.token.token_type == TokenType.BLOCK
                        and node.token.split_contents()[0] == "slot"):
                    if node.name in valid_slot_names and node.name in slots_filled:
                        nodelist.append(TextNode(slots_filled[node.name]))
                    else:
                        for node in node.nodelist:
                            nodelist.append(node)
                else:
                    nodelist.append(node)

            render_context = Context(context)
            with render_context.bind_template(template.template):
                return nodelist.render(render_context)

        return template.render(context)
Beispiel #2
0
def django_render_block(template, block_name, context):
    # Create a Django Context.
    context_instance = Context(context)

    # Get the underlying django.template.base.Template object.
    template = template.template

    # Bind the template to the context.
    with context_instance.bind_template(template):
        # Before trying to render the template, we need to traverse the tree of
        # parent templates and find all blocks in them.
        parent_template = _build_block_context(template, context_instance)

        try:
            return _render_template_block(template, block_name, context_instance)
        except BlockNotFound:
            # The block wasn't found in the current template.

            # If there's no parent template (i.e. no ExtendsNode), re-raise.
            if not parent_template:
                raise

            # Check the parent template for this block.
            return _render_template_block(
                parent_template, block_name, context_instance)
Beispiel #3
0
def django_render_block(template, block_name, context):
    # Create a Django Context.
    context_instance = Context(context)

    # Get the underlying django.template.base.Template object.
    template = template.template

    # Bind the template to the context.
    with context_instance.bind_template(template):
        # Before trying to render the template, we need to traverse the tree of
        # parent templates and find all blocks in them.
        parent_template = _build_block_context(template, context_instance)

        try:
            return _render_template_block(template, block_name,
                                          context_instance)
        except BlockNotFound:
            # The block wasn't found in the current template.

            # If there's no parent template (i.e. no ExtendsNode), re-raise.
            if not parent_template:
                raise

            # Check the parent template for this block.
            return _render_template_block(parent_template, block_name,
                                          context_instance)
Beispiel #4
0
def render_block_to_string(template_name, block_name, context=None):
    """
    Loads the given template_name and renders the given block with the given dictionary as
    context. Returns a string.

        template_name
            The name of the template to load and render. If it's a list of
            template names, Django uses select_template() instead of
            get_template() to find the template.
    """

    # Like render_to_string, template_name can be a string or a list/tuple.
    if isinstance(template_name, (tuple, list)):
        t = loader.select_template(template_name)
    else:
        t = loader.get_template(template_name)

    # Create the context instance.
    context = context or {}
    context_instance = Context(context)

    # This only works with the Django backend.
    if not isinstance(t, DjangoTemplate):
        raise UnsupportedEngine(
            'Can only render blocks from the Django template backend.')

    # Get the underlying django.template.base.Template object.
    t = t.template

    # Bind the template to the context.
    with context_instance.bind_template(t):
        return _render_template_block(t, block_name, context_instance)
Beispiel #5
0
def django_render_block(template, block_name, context):
    # Create a Django Context.
    context_instance = Context(context)

    # Get the underlying django.template.base.Template object.
    template = template.template

    # Bind the template to the context.
    with context_instance.bind_template(template):
        return _render_template_block(template, block_name, context_instance)
Beispiel #6
0
def send_templated_mail(template_name, from_email, to, bcc, context):
    template = get_template(template_name).template
    render_context = Context(context, autoescape=False)
    with render_context.bind_template(template):
        email = EmailMultiAlternatives(
            _get_node(template, render_context, 'subject'),
            _get_node(template, render_context, 'plain'),
            from_email=from_email,
            to=to,
            bcc=bcc)
        email.attach_alternative(
            _get_node(template, render_context, 'html'), 'text/html')
        email.send()
def build_message(template_names, extra_context=None, force_multipart=False,
                  inline_images=False, **defaults):
    if not isinstance(template_names, (list, tuple)):
        template_names = (template_names,)
    template = select_template(template_names).template

    blocks = {
        node.name: node
        for node in template.nodelist.get_nodes_by_type(BlockNode)
    }

    if extra_context is None:
        extra_context = {}
    extra_context = Context(extra_context)

    data = dict(defaults)
    data.setdefault('body', '')

    with extra_context.bind_template(template):
        # Scalar values
        for field in ('subject', 'from_email', 'body', 'html'):
            block = blocks.get(field)
            if block:
                data[field] = block.render(extra_context).strip()

        # List values
        for field in ('to', 'bcc', 'cc', 'reply_to'):
            block = blocks.get(field)
            if block:
                data[field] = [
                    line.strip()
                    for line in block.render(extra_context).splitlines()
                    if line.strip()
                ]

    html_content = data.pop('html', None)
    if force_multipart or html_content:
        msg = EmailMultiAlternatives(**data)
        if html_content:
            msg.attach_alternative(html_content, 'text/html')
        if inline_images:
            for att in extra_context.request_context.get('cid', []):
                msg.attach(att)
    else:
        msg = EmailMessage(**data)

    return msg
def build_message(template_names,
                  extra_context=None,
                  force_multipart=False,
                  **defaults):
    if not isinstance(template_names, (list, tuple)):
        template_names = (template_names, )
    template = select_template(template_names).template

    blocks = {
        node.name: node
        for node in template.nodelist.get_nodes_by_type(BlockNode)
    }

    if extra_context is None:
        extra_context = {}
    extra_context = Context(extra_context)

    data = dict(defaults)
    data.setdefault('body', '')

    with extra_context.bind_template(template):
        # Scalar values
        for field in ('subject', 'from_email', 'body', 'html'):
            block = blocks.get(field)
            if block:
                data[field] = block.render(extra_context).strip()

        # List values
        for field in ('to', 'bcc', 'cc', 'reply_to'):
            block = blocks.get(field)
            if block:
                data[field] = [
                    line.strip()
                    for line in block.render(extra_context).splitlines()
                    if line.strip()
                ]

    html_content = data.pop('html', None)
    if force_multipart or html_content:
        msg = EmailMultiAlternatives(**data)
        if html_content:
            msg.attach_alternative(html_content, 'text/html')
    else:
        msg = EmailMessage(**data)

    return msg
    def render(self, context=None, request=None, def_name=None):
        '''
        Renders a template using the Mako system.  This method signature conforms to
        the Django template API, which specifies that template.render() returns a string.

            @context  A dictionary of name=value variables to send to the template page.  This can be a real dictionary
                      or a Django Context object.
            @request  The request context from Django.  If this is None, any TEMPLATE_CONTEXT_PROCESSORS defined in your settings
                      file will be ignored but the template will otherwise render fine.
            @def_name Limits output to a specific top-level Mako <%block> or <%def> section within the template.
                      If the section is a <%def>, any parameters must be in the context dictionary.  For example,
                      def_name="foo" will call <%block name="foo"></%block> or <%def name="foo()"></def> within
                      the template.

        Returns the rendered template as a unicode string.

        The method triggers two signals:
            1. dmp_signal_pre_render_template: you can (optionally) return a new Mako Template object from a receiver to replace
               the normal template object that is used for the render operation.
            2. dmp_signal_post_render_template: you can (optionally) return a string to replace the string from the normal
               template object render.
        '''
        # set up the context dictionary, which is the variables available throughout the template
        context_dict = {}
        # if request is None, add some default items because the context processors won't happen
        if request is None:
            context_dict['settings'] = settings
            context_dict['STATIC_URL'] = settings.STATIC_URL
        # let the context_processors add variables to the context.
        if not isinstance(context, Context):
            context = Context(context) if request is None else RequestContext(
                request, context)
        with context.bind_template(self):
            for d in context:
                context_dict.update(d)
        context_dict.pop(
            'self', None
        )  # some contexts have self in them, and it messes up render_unicode below because we get two selfs

        # send the pre-render signal
        if DMP_OPTIONS['SIGNALS'] and request is not None:
            for receiver, ret_template_obj in dmp_signal_pre_render_template.send(
                    sender=self,
                    request=request,
                    context=context,
                    template=self.mako_template):
                if ret_template_obj is not None:
                    if isinstance(ret_template_obj, MakoTemplateAdapter):
                        self.mako_template = ret_template_obj.mako_template  # if the signal function sends a MakoTemplateAdapter back, use the real mako template inside of it
                    else:
                        self.mako_template = ret_template_obj  # if something else, we assume it is a mako.template.Template, so use it as the template

        # do we need to limit down to a specific def?
        # this only finds within the exact template (won't go up the inheritance tree)
        # I wish I could make it do so, but can't figure this out
        render_obj = self.mako_template
        if def_name is None:
            def_name = self.def_name
        if def_name:  # do we need to limit to just a def?
            render_obj = self.mako_template.get_def(def_name)

        # PRIMARY FUNCTION: render the template
        template_name = '%s::%s' % (self.mako_template.filename
                                    or 'string', def_name or 'body')
        if log.isEnabledFor(logging.INFO):
            log.info('rendering template %s', template_name)
        if settings.DEBUG:
            try:
                content = render_obj.render_unicode(**context_dict)
            except Exception as e:
                log.exception('exception raised during template rendering: %s',
                              e)  # to the console
                content = html_error_template().render_unicode(
                )  # to the browser
        else:  # this is outside the above "try" loop because in non-DEBUG mode, we want to let the exception throw out of here (without having to re-raise it)
            content = render_obj.render_unicode(**context_dict)

        # send the post-render signal
        if DMP_OPTIONS['SIGNALS'] and request is not None:
            for receiver, ret_content in dmp_signal_post_render_template.send(
                    sender=self,
                    request=request,
                    context=context,
                    template=self.mako_template,
                    content=content):
                if ret_content is not None:
                    content = ret_content  # sets it to the last non-None return in the signal receiver chain

        # return
        return content
Beispiel #10
0
  def render(self, request, template, params={}, def_name=None):
    '''Runs a template and returns a string.  Normally, you probably want to call render_to_response instead
       because it gives a full HttpResponse or Http404.

       This method raises a mako.exceptions.TopLevelLookupException if the template is not found.

       The method throws two signals:
         1. dmp_signal_pre_render_template: you can (optionally) return a new Mako Template object from a receiver to replace
            the normal template object that is used for the render operation.
         2. dmp_signal_post_render_template: you can (optionally) return a string to replace the string from the normal
            template object render.

       @request  The request context from Django.  If this is None, 1) any TEMPLATE_CONTEXT_PROCESSORS defined in your settings
                 file will be ignored and 2) DMP signals will not be sent, but the template will otherwise render fine.
       @template The template file path to render.  This is relative to the app_path/controller_TEMPLATES_DIR/ directory.
                 For example, to render app_path/templates/page1, set template="page1.html", assuming you have
                 set up the variables as described in the documentation above.
       @params   A dictionary of name=value variables to send to the template page.
       @def_name Limits output to a specific top-level Mako <%block> or <%def> section within the template.
                 If the section is a <%def>, it must have no parameters.  For example, def_name="foo" will call
                 <%block name="foo"></%block> or <%def name="foo()"></def> within the template.
                 The block/def must be defined in the exact template.  DMP does not support calling defs from
                 super-templates.
    '''
    # must convert the request context to a real dict to use the ** below
    context_dict = {}
    context_dict['request'] = request
    context_dict['settings'] = settings
    try:
      context_dict['STATIC_URL'] = settings.STATIC_URL  # this is used so much in templates, it's useful to have it always available
    except AttributeError:
      pass
    context = Context(params) if request == None else RequestContext(request, params)  # Django's RequestContext automatically runs all the TEMPLATE_CONTEXT_PROCESSORS and populates with variables
    with context.bind_template(self):
      for d in context:
        context_dict.update(d)

    # get the template
    template_obj = self.get_template(template)

    # send the pre-render signal
    if get_setting('SIGNALS', False) and request != None:
      for receiver, ret_template_obj in signals.dmp_signal_pre_render_template.send(sender=self, request=request, context=context, template=template_obj):
        if ret_template_obj != None:  # changes the template object to the received
          template_obj = ret_template_obj

    # do we need to limit down to a specific def?
    # this only finds within the exact template (won't go up the inheritance tree)
    # I wish I could make it do so, but can't figure this out
    render_obj = template_obj
    if def_name:  # do we need to limit to just a def?
      render_obj = template_obj.get_def(def_name)

    # PRIMARY FUNCTION: render the template
    log.debug('DMP :: rendering template %s' % template_obj.filename)
    if settings.DEBUG:
      try:
        content = render_obj.render_unicode(**context_dict)
      except:
        content = html_error_template().render_unicode()
    else:  # this is outside the above "try" loop because in non-DEBUG mode, we want to let the exception throw out of here (without having to re-raise it)
      content = render_obj.render_unicode(**context_dict)

    # send the post-render signal
    if get_setting('SIGNALS', False) and request != None:
      for receiver, ret_content in signals.dmp_signal_post_render_template.send(sender=self, request=request, context=context, template=template_obj, content=content):
        if ret_content != None:
          content = ret_content  # sets it to the last non-None return in the signal receiver chain

    # return
    return content
Beispiel #11
0
  def render(self, request, template, params={}, def_name=None):
    '''Runs a template and returns a string.  Normally, you probably want to call render_to_response instead
       because it gives a full HttpResponse or Http404.
       
       This method raises a mako.exceptions.TopLevelLookupException if the template is not found.
    
       The method throws two signals: 
         1. dmp_signal_pre_render_template: you can (optionally) return a new Mako Template object from a receiver to replace
            the normal template object that is used for the render operation.
         2. dmp_signal_post_render_template: you can (optionally) return a string to replace the string from the normal
            template object render.
    
       @request  The request context from Django.  If this is None, 1) any TEMPLATE_CONTEXT_PROCESSORS defined in your settings
                 file will be ignored and 2) DMP signals will not be sent, but the template will otherwise render fine.
       @template The template file path to render.  This is relative to the app_path/controller_TEMPLATES_DIR/ directory.
                 For example, to render app_path/templates/page1, set template="page1.html", assuming you have
                 set up the variables as described in the documentation above.
       @params   A dictionary of name=value variables to send to the template page.
       @def_name Limits output to a specific top-level Mako <%block> or <%def> section within the template.
                 If the section is a <%def>, it must have no parameters.  For example, def_name="foo" will call
                 <%block name="foo"></%block> or <%def name="foo()"></def> within the template.
                 The block/def must be defined in the exact template.  DMP does not support calling defs from 
                 super-templates.
    '''
    # must convert the request context to a real dict to use the ** below
    context_dict = {}
    context_dict['request'] = request
    context_dict['settings'] = settings
    try:
      context_dict['STATIC_URL'] = settings.STATIC_URL  # this is used so much in templates, it's useful to have it always available
    except AttributeError:
      pass
    context = Context(params) if request == None else RequestContext(request, params)  # Django's RequestContext automatically runs all the TEMPLATE_CONTEXT_PROCESSORS and populates with variables
    with context.bind_template(self):
      for d in context:
        context_dict.update(d)

    # get the template
    template_obj = self.get_template(template)

    # send the pre-render signal
    if get_setting('SIGNALS', False) and request != None:
      for receiver, ret_template_obj in signals.dmp_signal_pre_render_template.send(sender=self, request=request, context=context, template=template_obj):
        if ret_template_obj != None:  # changes the template object to the received
          template_obj = ret_template_obj

    # do we need to limit down to a specific def?
    # this only finds within the exact template (won't go up the inheritance tree)
    # I wish I could make it do so, but can't figure this out
    render_obj = template_obj  
    if def_name:  # do we need to limit to just a def?
      render_obj = template_obj.get_def(def_name)

    # PRIMARY FUNCTION: render the template
    log.debug('DMP :: rendering template %s' % template_obj.filename)
    if settings.DEBUG:
      try:
        content = render_obj.render_unicode(**context_dict)
      except:
        content = html_error_template().render_unicode()
    else:  # this is outside the above "try" loop because in non-DEBUG mode, we want to let the exception throw out of here (without having to re-raise it)
      content = render_obj.render_unicode(**context_dict)
      
    # send the post-render signal
    if get_setting('SIGNALS', False) and request != None:
      for receiver, ret_content in signals.dmp_signal_post_render_template.send(sender=self, request=request, context=context, template=template_obj, content=content):
        if ret_content != None:
          content = ret_content  # sets it to the last non-None return in the signal receiver chain
          
    # return
    return content