Repository: nautobot/nautobot

Issue:
Computed Fields - TemplateError Crash
<!--
    NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.

    This form is only for reporting reproducible bugs. If you need assistance
    with Nautobot installation, or if you have a general question, please start a
    discussion instead: https://github.com/nautobot/nautobot/discussions

    Please describe the environment in which you are running Nautobot. Be sure
    that you are running an unmodified instance of the latest stable release
    before submitting a bug report, and that any plugins have been disabled.
-->
### Environment
* Python version: 3.6
* Nautobot version: 1.1.0b2

<!--
    Describe in detail the exact steps that someone else can take to reproduce
    this bug using the current stable release of Nautobot. Begin with the
    creation of any necessary database objects and call out every operation
    being performed explicitly. If reporting a bug in the REST API, be sure to
    reconstruct the raw HTTP request(s) being made: Don't rely on a client
    library such as pynautobot.
-->
### Steps to Reproduce
1. Create a service with an IP address
2. Create a computed field for `ipam | service`
 ![image](https://user-images.githubusercontent.com/29315002/125703612-ca5e5fa0-7664-4b5d-86e2-31277381bf01.png)
3. Navigate to service and see the failure (screenshot is in debug mode)
![image](https://user-images.githubusercontent.com/29315002/125703758-af4fa38d-a98b-4b90-ae8a-9d5cbca06b4f.png)


<!-- What did you expect to happen? -->
### Expected Behavior
Swallow the exception and use the **Fallback Value**

<!-- What happened instead? -->
### Observed Behavior
Exception from the **Steps to Reproduce**



Discussion:

Resolving patch:
diff --git a/nautobot/extras/models/customfields.py b/nautobot/extras/models/customfields.py
--- a/nautobot/extras/models/customfields.py
+++ b/nautobot/extras/models/customfields.py
@@ -10,7 +10,6 @@
 from django.db import models
 from django.urls import reverse
 from django.utils.safestring import mark_safe
-from jinja2 import TemplateError
 
 from nautobot.extras.choices import *
 from nautobot.extras.models import ChangeLoggedModel
@@ -81,8 +80,8 @@ def get_absolute_url(self):
     def render(self, context):
         try:
             return render_jinja2(self.template, context)
-        except TemplateError as e:
-            logger.warning("Failed to render computed field %s: %s", self.slug, e)
+        except Exception as exc:
+            logger.warning("Failed to render computed field %s: %s", self.slug, exc)
             return self.fallback_value
 
 


Test patch:
diff --git a/nautobot/extras/tests/test_customfields.py b/nautobot/extras/tests/test_customfields.py
--- a/nautobot/extras/tests/test_customfields.py
+++ b/nautobot/extras/tests/test_customfields.py
@@ -773,6 +773,7 @@ def setUp(self):
             fallback_value="An error occurred while rendering this template.",
             weight=100,
         )
+        # Field whose template will raise a TemplateError
         self.bad_computed_field = ComputedField.objects.create(
             content_type=ContentType.objects.get_for_model(Site),
             slug="bad_computed_field",
@@ -781,6 +782,15 @@ def setUp(self):
             fallback_value="This template has errored",
             weight=100,
         )
+        # Field whose template will raise a TypeError
+        self.worse_computed_field = ComputedField.objects.create(
+            content_type=ContentType.objects.get_for_model(Site),
+            slug="worse_computed_field",
+            label="Worse Computed Field",
+            template="{{ obj.images | list }}",
+            fallback_value="Another template error",
+            weight=200,
+        )
         self.non_site_computed_field = ComputedField.objects.create(
             content_type=ContentType.objects.get_for_model(Device),
             slug="device_computed_field",
@@ -857,6 +867,7 @@ def test_get_computed_fields_method(self):
         expected_renderings = {
             "computed_field_one": f"{self.site1.name} is the name of this site.",
             "bad_computed_field": self.bad_computed_field.fallback_value,
+            "worse_computed_field": self.worse_computed_field.fallback_value,
         }
         self.assertDictEqual(self.site1.get_computed_fields(), expected_renderings)
 
@@ -864,6 +875,7 @@ def test_get_computed_fields_method_label_as_key(self):
         expected_renderings = {
             "Computed Field One": f"{self.site1.name} is the name of this site.",
             "Bad Computed Field": self.bad_computed_field.fallback_value,
+            "Worse Computed Field": self.worse_computed_field.fallback_value,
         }
         self.assertDictEqual(self.site1.get_computed_fields(label_as_key=True), expected_renderings)