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)
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)
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)
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)
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)
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
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