From 9f453009999922a4589c6289cd61866acf74afcb Mon Sep 17 00:00:00 2001 From: Rob Duffy Date: Tue, 26 Nov 2024 15:51:05 +0100 Subject: [PATCH 1/4] Fixes #17490: Config Template unable to dynamically include templates --- netbox/utilities/jinja2.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/netbox/utilities/jinja2.py b/netbox/utilities/jinja2.py index cefb97831d9..8286ae17130 100644 --- a/netbox/utilities/jinja2.py +++ b/netbox/utilities/jinja2.py @@ -29,10 +29,16 @@ def get_source(self, environment, template): # Find and pre-fetch referenced templates if referenced_templates := find_referenced_templates(environment.parse(template_source)): - self.cache_templates({ - df.path: df.data_as_string for df in - DataFile.objects.filter(source=self.data_source, path__in=referenced_templates) - }) + if None in referenced_templates: + self.cache_templates({ + df.path: df.data_as_string for df in + DataFile.objects.filter(source=self.data_source) + }) + else: + self.cache_templates({ + df.path: df.data_as_string for df in + DataFile.objects.filter(source=self.data_source, path__in=referenced_templates) + }) return template_source, template, lambda: True From 9930fef28b152d431544998847a2b4a1d23e9d9a Mon Sep 17 00:00:00 2001 From: Rob Duffy Date: Mon, 2 Dec 2024 20:25:57 +0100 Subject: [PATCH 2/4] Cast the generator returned by find_referenced_templates() to an iterable to avoid exhausting it on the check for None Co-authored-by: Jeremy Stretch --- netbox/utilities/jinja2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netbox/utilities/jinja2.py b/netbox/utilities/jinja2.py index 8286ae17130..dd2f083adce 100644 --- a/netbox/utilities/jinja2.py +++ b/netbox/utilities/jinja2.py @@ -28,7 +28,7 @@ def get_source(self, environment, template): raise TemplateNotFound(template) # Find and pre-fetch referenced templates - if referenced_templates := find_referenced_templates(environment.parse(template_source)): + if referenced_templates := tuple(find_referenced_templates(environment.parse(template_source))): if None in referenced_templates: self.cache_templates({ df.path: df.data_as_string for df in From 5173a490b827ccf12b117acbf44f9cd7beda2c63 Mon Sep 17 00:00:00 2001 From: Rob Duffy Date: Mon, 2 Dec 2024 20:26:19 +0100 Subject: [PATCH 3/4] Apply the path__in filter to avoid duplicating code Co-authored-by: Jeremy Stretch --- netbox/utilities/jinja2.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/netbox/utilities/jinja2.py b/netbox/utilities/jinja2.py index dd2f083adce..9f87d3f287e 100644 --- a/netbox/utilities/jinja2.py +++ b/netbox/utilities/jinja2.py @@ -30,15 +30,14 @@ def get_source(self, environment, template): # Find and pre-fetch referenced templates if referenced_templates := tuple(find_referenced_templates(environment.parse(template_source))): if None in referenced_templates: - self.cache_templates({ - df.path: df.data_as_string for df in - DataFile.objects.filter(source=self.data_source) - }) - else: - self.cache_templates({ - df.path: df.data_as_string for df in - DataFile.objects.filter(source=self.data_source, path__in=referenced_templates) - }) + related_files = DataFile.objects.filter(source=self.data_source) + # None indicates the use of dynamic resolution. If dependent files are statically + # defined, we can filter by path for optimization. + if None not in referenced_templates: + related_files = related_files.filter(path__in=referenced_templates) + self.cache_templates({ + df.path: df.data_as_string for df in related_files + }) return template_source, template, lambda: True From 20c02350065712e7fe75904a3a6697884abbb670 Mon Sep 17 00:00:00 2001 From: Rob Duffy Date: Mon, 2 Dec 2024 19:58:11 +0000 Subject: [PATCH 4/4] Remove extra if None not in referenced_templates --- netbox/utilities/jinja2.py | 1 - 1 file changed, 1 deletion(-) diff --git a/netbox/utilities/jinja2.py b/netbox/utilities/jinja2.py index 9f87d3f287e..cea8c9029ca 100644 --- a/netbox/utilities/jinja2.py +++ b/netbox/utilities/jinja2.py @@ -29,7 +29,6 @@ def get_source(self, environment, template): # Find and pre-fetch referenced templates if referenced_templates := tuple(find_referenced_templates(environment.parse(template_source))): - if None in referenced_templates: related_files = DataFile.objects.filter(source=self.data_source) # None indicates the use of dynamic resolution. If dependent files are statically # defined, we can filter by path for optimization.