nautobot-app-ssot
nautobot-app-ssot copied to clipboard
Unable to open /plugins/ssot/history/ on one of my nautobot instance
Environment
-
Python version: 3.11.9
-
Nautobot version: 2.2.4
-
nautobot-ssot version: How can I get that? probably 2.6.1
Expected Behavior
The /plugins/ssot/history/ would show
Observed Behavior
An error message was shown instead:
AttributeError at /plugins/ssot/history/
'NoneType' object has no attribute 'class_path'
Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/
Django Version: 3.2.25
Exception Type: AttributeError
Exception Value:
'NoneType' object has no attribute 'class_path'
Exception Location: /opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py, line 137, in get_source_url
Python Executable: /usr/local/bin/python3.11
Python Version: 3.11.9
Python Path:
['.',
'',
'/opt/nautobot',
'/usr/local/bin',
'/usr/local/lib/python311.zip',
'/usr/local/lib/python3.11',
'/usr/local/lib/python3.11/lib-dynload',
'/opt/nautobot/.local/lib/python3.11/site-packages',
'/usr/local/lib/python3.11/site-packages']
Server time: Tue, 09 Jul 2024 16:10:41 +0200
Here is the complete traceback:
Environment:
Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/
Django Version: 3.2.25
Python Version: 3.11.9
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'corsheaders',
'django_filters',
'django_jinja',
'django_tables2',
'django_prometheus',
'social_django',
'taggit',
'timezone_field',
'nautobot.core.apps.NautobotConstanceConfig',
'nautobot.core',
'django.contrib.admin',
'django_celery_beat',
'django_celery_results',
'rest_framework',
'db_file_storage',
'nautobot.circuits',
'nautobot.dcim',
'nautobot.ipam',
'nautobot.extras',
'nautobot.tenancy',
'nautobot.users',
'nautobot.virtualization',
'drf_spectacular',
'drf_spectacular_sidecar',
'graphene_django',
'health_check',
'health_check.storage',
'django_extensions',
'constance.backends.database',
'django_ajax_tables',
'silk',
'nautobot_device_lifecycle_mgmt.NautobotDeviceLifecycleManagementConfig',
'nautobot_ssot.NautobotSSOTAppConfig',
'nautobot_secrets_providers.NautobotSecretsProvidersConfig']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'silk.middleware.SilkyMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'nautobot.core.middleware.ExceptionHandlingMiddleware',
'nautobot.core.middleware.RemoteUserMiddleware',
'nautobot.core.middleware.ExternalAuthMiddleware',
'nautobot.core.middleware.ObjectChangeMiddleware',
'django_prometheus.middleware.PrometheusAfterMiddleware']
Template error:
In template /usr/local/lib/python3.11/site-packages/nautobot/core/templates/inc/table.html, error at line 20
'NoneType' object has no attribute 'class_path'
10 : {% else %}
11 : <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
12 : {% endif %}
13 : {% endfor %}
14 : </tr>
15 : </thead>
16 : {% endif %}
17 : <tbody>
18 : {% for row in table.page.object_list|default:table.rows %}
19 : <tr {{ row.attrs.as_html }}>
20 : {% for column, cell in row.items %}
21 : <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
22 : {% endfor %}
23 : </tr>
24 : {% empty %}
25 : {% if table.empty_text %}
26 : <tr>
27 : <td colspan="{{ table.columns|length }}" class="text-center text-muted">— {{ table.empty_text }} —</td>
28 : </tr>
29 : {% endif %}
30 : {% endfor %}
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 47, in inner
response = get_response(request)
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/mixins.py", line 166, in dispatch
return super().dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/generic.py", line 348, in get
return render(request, self.template_name, context)
File "/usr/local/lib/python3.11/site-packages/django/shortcuts.py", line 19, in render
content = loader.render_to_string(template_name, context, request, using=using)
File "/usr/local/lib/python3.11/site-packages/django/template/loader.py", line 62, in render_to_string
return template.render(context, request)
File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 170, in render
return self._render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
return compiled_parent._render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
return compiled_parent._render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 150, in render
return compiled_parent._render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 62, in render
result = block.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 62, in render
result = block.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 519, in render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 315, in render
return nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 195, in render
return template.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 172, in render
return self._render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 315, in render
return nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django_tables2/templatetags/django_tables2.py", line 166, in render
return template.render(context={"table": table}, request=request)
File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 170, in render
return self._render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 162, in _render
return self.nodelist.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 938, in render
bit = node.render_annotated(context)
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 214, in render
nodelist.append(node.render_annotated(context))
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 905, in render_annotated
return self.render(context)
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 170, in render
values = list(values)
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 244, in items
column.current_value = self.get_cell(column.name)
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 197, in get_cell
return self._get_and_render_with(
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
return render_func(bound_column, value)
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 208, in _call_render
return bound_column.link(content, **render_kwargs) if bound_column.link else content
File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 153, in __call__
attrs = self.get_attrs(**kwargs)
File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 148, in get_attrs
attrs["href"] = self.compose_url(**kwargs)
File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 100, in compose_url
return call_with_appropriate(self.url, kwargs)
File "/usr/local/lib/python3.11/site-packages/django_tables2/utils.py", line 572, in call_with_appropriate
return fn(**kwargs)
File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/tables.py", line 60, in <lambda>
source = Column(linkify=lambda record: record.get_source_url())
File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 137, in get_source_url
kwargs={"class_path": self.job_result.job_model.class_path},
Exception Type: AttributeError at /plugins/ssot/history/
Exception Value: 'NoneType' object has no attribute 'class_path'
Steps to Reproduce
I do not realy know... I can only give you a lead, which is what I did.
- Import jobs using git
- Change/move jobs around, resyncing them
- Try to access /plugins/ssot/history/
My interpretation here is that SSOT get_source_url() is not accounting for the possibility that there is a JobResult from a Job that has subsequently been uninstalled or deleted.
Ran into this as well, seemed like exactly that. After I had deleted all my not installed apps after a git repo sync then this began to occur in the dashboard and the history. Though the history is giving a <class 'MemoryError'> and the Dashboard is giving me AttributeError: 'NoneType' object has no attribute 'class_path'
Should be a straight-forward fix, to check if the job result exists here:
File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 137, in get_source_url
kwargs={"class_path": self.job_result.job_model.class_path},
@dylanbob
nautobot-ssot version: How can I get that? probably 2.6.1
Under Apps -> Installed Apps or with pip show
As for the actual issue, we have found that we are unable to replicate this, at least consistently. Are you able to do this?
Hi. My environment changed since I opened this issue, now I have:
- Python version: 3.11.9
- Nautobot version: 2.3.1
- nautobot-ssot version: 3.0.1
I was in 2.6.1 when I opened the issue.
I was able to reproduce the issue right now. Steps :
- import a job, using git (in my particular case)
- execute the job
- delete the job
- try to access /plugins/ssot/history/
At 4., the error occurs, here is the traceback:
Environment:
Request Method: GET
Request URL: https://xxx.xxx.xxx.xxx/plugins/ssot/history/
Django Version: 4.2.15
Python Version: 3.11.9
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'corsheaders',
'django_filters',
'django_jinja',
'django_tables2',
'django_prometheus',
'social_django',
'taggit',
'timezone_field',
'nautobot.core.apps.NautobotConstanceConfig',
'nautobot.core',
'django.contrib.admin',
'django_celery_beat',
'django_celery_results',
'rest_framework',
'db_file_storage',
'nautobot.circuits',
'nautobot.cloud',
'nautobot.dcim',
'nautobot.ipam',
'nautobot.extras',
'nautobot.tenancy',
'nautobot.users',
'nautobot.virtualization',
'drf_spectacular',
'drf_spectacular_sidecar',
'graphene_django',
'health_check',
'health_check.storage',
'django_extensions',
'django_ajax_tables',
'silk',
'nautobot_ssot.NautobotSSOTAppConfig',
'nautobot_secrets_providers.NautobotSecretsProvidersConfig']
Installed Middleware:
['django_prometheus.middleware.PrometheusBeforeMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'silk.middleware.SilkyMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'nautobot.core.middleware.ExceptionHandlingMiddleware',
'nautobot.core.middleware.RemoteUserMiddleware',
'nautobot.core.middleware.ExternalAuthMiddleware',
'nautobot.core.middleware.ObjectChangeMiddleware',
'django_prometheus.middleware.PrometheusAfterMiddleware']
Template error:
In template /usr/local/lib/python3.11/site-packages/nautobot/core/templates/inc/table.html, error at line 20
'NoneType' object has no attribute 'class_path'
10 : {% else %}
11 : <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
12 : {% endif %}
13 : {% endfor %}
14 : </tr>
15 : </thead>
16 : {% endif %}
17 : <tbody>
18 : {% for row in table.page.object_list|default:table.rows %}
19 : <tr {{ row.attrs.as_html }}>
20 : {% for column, cell in row.items %}
21 : <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
22 : {% endfor %}
23 : </tr>
24 : {% empty %}
25 : {% if table.empty_text %}
26 : <tr>
27 : <td colspan="{{ table.columns|length }}" class="text-center text-muted">— {{ table.empty_text }} —</td>
28 : </tr>
29 : {% endif %}
30 : {% endfor %}
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/exception.py", line 55, in inner
response = get_response(request)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/core/handlers/base.py", line 197, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 104, in view
return self.dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/mixins.py", line 168, in dispatch
return super().dispatch(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/views/generic/base.py", line 143, in dispatch
return handler(request, *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/nautobot/core/views/generic.py", line 391, in get
return render(request, self.template_name, context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/shortcuts.py", line 24, in render
content = loader.render_to_string(template_name, context, request, using=using)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader.py", line 62, in render_to_string
return template.render(context, request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 175, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 157, in render
return compiled_parent._render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 63, in render
result = block.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 63, in render
result = block.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 541, in render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 321, in render
return nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/loader_tags.py", line 208, in render
return template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 177, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 321, in render
return nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/templatetags/django_tables2.py", line 166, in render
return template.render(context={"table": table}, request=request)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/backends/django.py", line 61, in render
return self.template.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 175, in render
return self._render(context)
^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 167, in _render
return self.nodelist.render(context)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in render
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 1005, in <listcomp>
return SafeString("".join([node.render_annotated(context) for node in self]))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 238, in render
nodelist.append(node.render_annotated(context))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/base.py", line 966, in render_annotated
return self.render(context)
^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django/template/defaulttags.py", line 193, in render
values = list(values)
^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 244, in items
column.current_value = self.get_cell(column.name)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 197, in get_cell
return self._get_and_render_with(
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 173, in _get_and_render_with
return render_func(bound_column, value)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/rows.py", line 208, in _call_render
return bound_column.link(content, **render_kwargs) if bound_column.link else content
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 153, in __call__
attrs = self.get_attrs(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 148, in get_attrs
attrs["href"] = self.compose_url(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/columns/base.py", line 100, in compose_url
return call_with_appropriate(self.url, kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/django_tables2/utils.py", line 572, in call_with_appropriate
return fn(**kwargs)
^^^^^^^^^^^^
File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/tables.py", line 58, in <lambda>
source = Column(linkify=lambda record: record.get_source_url())
^^^^^^^^^^^^^^^^^^^^^^^
File "/opt/nautobot/.local/lib/python3.11/site-packages/nautobot_ssot/models.py", line 138, in get_source_url
kwargs={"class_path": self.job_result.job_model.class_path},
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Exception Type: AttributeError at /plugins/ssot/history/
Exception Value: 'NoneType' object has no attribute 'class_path'
@Kircheneer @dylanbob
I'm still unable to replicate this issue in my environment.
I have:
- Nautobot v2.3.1
- SSoT App v3.0.1
- Python v3.11
Steps I took:
- Imported SSoT jobs via Git repository
- Ran job from Git repo a couple times
- Deleted jobs by deleting get repo from Nautobot
When I go to /plugins/ssot/history/, I don't get any errors.
I do get 404 errors when I try to open up one of the links to the missing job, though it's not the same error as described.
Reviewing this and the error from @dylanbob I believe this is an issue with your Job being installed correctly. The NoneType in question is the job_model so you need to fix that.