Closes #18797: Support path import for certain Jinja environment parameters (#19962)

* Closes #18797: Support path import for certain Jinja environment parameters

* Document dotted path support for Jinja env params
This commit is contained in:
Jeremy Stretch 2025-07-29 10:09:25 -04:00 committed by GitHub
parent 6ba6ff3fee
commit 063d1fef7a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 4 deletions

View File

@ -24,6 +24,14 @@ Jinja2 template code, if being defined locally rather than replicated from a dat
A dictionary of any additional parameters to pass when instantiating the [Jinja2 environment](https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.Environment). Jinja2 supports various optional parameters which can be used to modify its default behavior. A dictionary of any additional parameters to pass when instantiating the [Jinja2 environment](https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.Environment). Jinja2 supports various optional parameters which can be used to modify its default behavior.
The `undefined` and `finalize` Jinja environment parameters, which must reference a Python class or function, can define a dotted path to the desired resource. For example:
```json
{
"undefined": "jinja2.StrictUndefined"
}
```
### MIME Type ### MIME Type
!!! info "This field was introduced in NetBox v4.3." !!! info "This field was introduced in NetBox v4.3."

View File

@ -26,6 +26,14 @@ Jinja2 template code for rendering the exported data.
A dictionary of any additional parameters to pass when instantiating the [Jinja2 environment](https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.Environment). Jinja2 supports various optional parameters which can be used to modify its default behavior. A dictionary of any additional parameters to pass when instantiating the [Jinja2 environment](https://jinja.palletsprojects.com/en/3.1.x/api/#jinja2.Environment). Jinja2 supports various optional parameters which can be used to modify its default behavior.
The `undefined` and `finalize` Jinja environment parameters, which must reference a Python class or function, can define a dotted path to the desired resource. For example:
```json
{
"undefined": "jinja2.StrictUndefined"
}
```
### MIME Type ### MIME Type
The MIME type to indicate in the response when rendering the export template (optional). Defaults to `text/plain`. The MIME type to indicate in the response when rendering the export template (optional). Defaults to `text/plain`.

View File

@ -21,6 +21,12 @@ WEBHOOK_EVENT_TYPES = {
JOB_ERRORED: 'job_ended', JOB_ERRORED: 'job_ended',
} }
# Jinja environment parameters which support path imports
JINJA_ENV_PARAMS_WITH_PATH_IMPORT = (
'undefined',
'finalize',
)
# Dashboard # Dashboard
DEFAULT_DASHBOARD = [ DEFAULT_DASHBOARD = [
{ {

View File

@ -2,16 +2,17 @@ import importlib.abc
import importlib.util import importlib.util
import os import os
import sys import sys
from django.core.files.storage import storages from django.core.files.storage import storages
from django.db import models from django.db import models
from django.utils.translation import gettext_lazy as _
from django.http import HttpResponse from django.http import HttpResponse
from django.utils.module_loading import import_string
from django.utils.translation import gettext_lazy as _
from extras.constants import DEFAULT_MIME_TYPE from extras.constants import DEFAULT_MIME_TYPE, JINJA_ENV_PARAMS_WITH_PATH_IMPORT
from extras.utils import filename_from_model, filename_from_object from extras.utils import filename_from_model, filename_from_object
from utilities.jinja2 import render_jinja2 from utilities.jinja2 import render_jinja2
__all__ = ( __all__ = (
'PythonModuleMixin', 'PythonModuleMixin',
'RenderTemplateMixin', 'RenderTemplateMixin',
@ -125,12 +126,22 @@ class RenderTemplateMixin(models.Model):
class_name=self.__class__ class_name=self.__class__
)) ))
def get_environment_params(self):
"""
Pre-processing of any defined Jinja environment parameters (e.g. to support path resolution).
"""
params = self.environment_params or {}
for name, value in params.items():
if name in JINJA_ENV_PARAMS_WITH_PATH_IMPORT and type(value) is str:
params[name] = import_string(value)
return params
def render(self, context=None, queryset=None): def render(self, context=None, queryset=None):
""" """
Render the template with the provided context. The context is passed to the Jinja2 environment as a dictionary. Render the template with the provided context. The context is passed to the Jinja2 environment as a dictionary.
""" """
context = self.get_context(context=context, queryset=queryset) context = self.get_context(context=context, queryset=queryset)
env_params = self.environment_params or {} env_params = self.get_environment_params()
output = render_jinja2(self.template_code, context, env_params, getattr(self, 'data_file', None)) output = render_jinja2(self.template_code, context, env_params, getattr(self, 'data_file', None))
# Replace CRLF-style line terminators # Replace CRLF-style line terminators