Bläddra i källkod

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
Jeremy Stretch 6 månader sedan
förälder
incheckning
063d1fef7a

+ 8 - 0
docs/models/extras/configtemplate.md

@@ -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.
 
+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
 
 !!! info "This field was introduced in NetBox v4.3."

+ 8 - 0
docs/models/extras/exporttemplate.md

@@ -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.
 
+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
 
 The MIME type to indicate in the response when rendering the export template (optional). Defaults to `text/plain`.

+ 6 - 0
netbox/extras/constants.py

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

+ 15 - 4
netbox/extras/models/mixins.py

@@ -2,16 +2,17 @@ import importlib.abc
 import importlib.util
 import os
 import sys
+
 from django.core.files.storage import storages
 from django.db import models
-from django.utils.translation import gettext_lazy as _
 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 utilities.jinja2 import render_jinja2
 
-
 __all__ = (
     'PythonModuleMixin',
     'RenderTemplateMixin',
@@ -125,12 +126,22 @@ class RenderTemplateMixin(models.Model):
             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):
         """
         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)
-        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))
 
         # Replace CRLF-style line terminators