def missingvalue(message): """ Raise an UndefinedError This function is made available to the template so that it can report when required values are not present and cause template rendering to fail. """ raise jinja2.UndefinedError(message)
def render(yaml, template): '''Render Jinja template string using YAML dict''' env = jinja2.Environment(undefined=jinja2.DebugUndefined) template = env.from_string(template) rendered = template.render(yaml) # Check if rendering was done correctly ast = env.parse(rendered) undefined = find_undeclared_variables(ast) if undefined: raise jinja2.UndefinedError(f'Variables are undefined: {undefined!r}') return rendered
def render(cls, template, context): """Renders a template string with Jinja. Args: template_string (str): The template string to be rendered context (dict): The context used for rendering Returns: str: The rendered string Raises: jinja2.UndefinedError: If a variable is undefined jinja2.TemplateError: If the template contains an invalid syntax """ try: return cls.__env.from_string(template).render(context) except jinja2.UndefinedError as e: raise jinja2.UndefinedError(f"Undefined variable: {e.message}") except jinja2.TemplateError as e: raise jinja2.TemplateError( f"Jinja template error: {e.message}")
def from_question( question: 'Question', data: Optional[dict] = None, errors: Optional[dict] = None, **kwargs ) -> Renderable: """Create parameters object for govuk-frontend macros from a question `from_question()` takes a `Question` and returns a dict containing the name of the govuk-frontend macro to call and the parameters to call it with, as well as associated components such as labels or fieldsets. >>> from dmcontent import Question >>> from_question(Question({'id': 'q1', 'type': 'text', 'question': ...}) {'label': {...}, 'macro_name': 'govukInput', 'params': {...}} Calling the macro(s) with the parameters is then done by `render()`, below. If `render()` and all the macros you need are in your template environment, then no extra Jinja magic is required. `from_question()` mainly just takes care of dispatching the `Question` object to the right function (defined below) for further processing; if you need to handle a new type of `Question` try and follow that pattern. :param question: A Question or QuestionSummary :param data: A dict that may contain the answer for question :param errors: A dict which may contain an error message for the question :returns: A dict with the macro name, macro parameters, and labels, or None if we don't know how to handle this type of question """ if question.type == "text" or question.type == "number": return { "label": govuk_label(question, **kwargs), "macro_name": "govukInput", "params": govuk_input(question, data, errors, **kwargs), } elif question.type == "pricing": return dm_pricing_input(question, data, errors, **kwargs) elif question.type == "date": return { "fieldset": govuk_fieldset(question, **kwargs), "macro_name": "govukDateInput", "params": govuk_date_input(question, data, errors, **kwargs), } elif question.type == "list": return { "macro_name": "dmListInput", "params": dm_list_input(question, data, errors, **kwargs) } elif question.type == "radios": return { "fieldset": govuk_fieldset(question, **kwargs), "macro_name": "govukRadios", "params": govuk_radios(question, data, errors, **kwargs) } elif question.type == "checkboxes": return { "fieldset": govuk_fieldset(question, **kwargs), "macro_name": "govukCheckboxes", "params": govuk_checkboxes(question, data, errors, **kwargs) } elif question.type == "boolean": return { "fieldset": govuk_fieldset(question, **kwargs), "macro_name": "govukRadios", "params": govuk_radios(question, data, errors, **kwargs) } elif question.type == "textbox_large": return { "label": govuk_label(question, **kwargs), "macro_name": "govukCharacterCount", "params": govuk_character_count(question, data, errors, **kwargs) } elif question.type == "upload": return { "macro_name": "govukFileUpload", "params": govuk_file_upload(question, data, errors, **kwargs) } elif question.type == "multiquestion": return dm_multiquestion(question, data, errors, **kwargs) else: raise jinja2.UndefinedError(f"unable to render question of type '{question.type}'")