diff --git a/docs/release-notes/version-2.8.md b/docs/release-notes/version-2.8.md
index e75bf4ab9..62d5e9920 100644
--- a/docs/release-notes/version-2.8.md
+++ b/docs/release-notes/version-2.8.md
@@ -1,5 +1,13 @@
# NetBox v2.8
+## v2.8.3 (FUTURE)
+
+### Bug Fixes
+
+* [#4593](https://github.com/netbox-community/netbox/issues/4593) - Fix AttributeError exception when viewing object lists as a non-authenticated user
+
+---
+
## v2.8.2 (2020-05-06)
### Enhancements
diff --git a/netbox/extras/views.py b/netbox/extras/views.py
index 613e45132..1bfbb7abf 100644
--- a/netbox/extras/views.py
+++ b/netbox/extras/views.py
@@ -124,9 +124,12 @@ class ConfigContextView(PermissionRequiredMixin, View):
# Determine user's preferred output format
if request.GET.get('format') in ['json', 'yaml']:
format = request.GET.get('format')
- request.user.config.set('extras.configcontext.format', format, commit=True)
- else:
+ if request.user.is_authenticated:
+ request.user.config.set('extras.configcontext.format', format, commit=True)
+ elif request.user.is_authenticated:
format = request.user.config.get('extras.configcontext.format', 'json')
+ else:
+ format = 'json'
return render(request, 'extras/configcontext.html', {
'configcontext': configcontext,
@@ -181,9 +184,12 @@ class ObjectConfigContextView(View):
# Determine user's preferred output format
if request.GET.get('format') in ['json', 'yaml']:
format = request.GET.get('format')
- request.user.config.set('extras.configcontext.format', format, commit=True)
- else:
+ if request.user.is_authenticated:
+ request.user.config.set('extras.configcontext.format', format, commit=True)
+ elif request.user.is_authenticated:
format = request.user.config.get('extras.configcontext.format', 'json')
+ else:
+ format = 'json'
return render(request, 'extras/object_configcontext.html', {
model_name: obj,
diff --git a/netbox/templates/utilities/obj_list.html b/netbox/templates/utilities/obj_list.html
index 4cfa8b1ce..85ff050ed 100644
--- a/netbox/templates/utilities/obj_list.html
+++ b/netbox/templates/utilities/obj_list.html
@@ -5,7 +5,7 @@
{% block content %}
{% block buttons %}{% endblock %}
- {% if table_config_form %}
+ {% if request.user.is_authenticated and table_config_form %}
{% endif %}
{% if permissions.add and 'add' in action_buttons %}
diff --git a/netbox/utilities/paginator.py b/netbox/utilities/paginator.py
index cef7c941f..cdad1f230 100644
--- a/netbox/utilities/paginator.py
+++ b/netbox/utilities/paginator.py
@@ -50,9 +50,12 @@ def get_paginate_count(request):
if 'per_page' in request.GET:
try:
per_page = int(request.GET.get('per_page'))
- request.user.config.set('pagination.per_page', per_page, commit=True)
+ if request.user.is_authenticated:
+ request.user.config.set('pagination.per_page', per_page, commit=True)
return per_page
except ValueError:
pass
- return request.user.config.get('pagination.per_page', settings.PAGINATE_COUNT)
+ if request.user.is_authenticated:
+ return request.user.config.get('pagination.per_page', settings.PAGINATE_COUNT)
+ return settings.PAGINATE_COUNT
diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py
index 3064abe4e..4b5993c5f 100644
--- a/netbox/utilities/views.py
+++ b/netbox/utilities/views.py
@@ -3,6 +3,7 @@ import sys
from copy import deepcopy
from django.contrib import messages
+from django.contrib.auth.decorators import login_required
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldDoesNotExist, ValidationError
from django.db import transaction, IntegrityError
@@ -13,6 +14,7 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.template import loader
from django.template.exceptions import TemplateDoesNotExist
from django.urls import reverse
+from django.utils.decorators import method_decorator
from django.utils.html import escape
from django.utils.http import is_safe_url
from django.utils.safestring import mark_safe
@@ -164,7 +166,10 @@ class ObjectListView(View):
permissions[action] = request.user.has_perm(perm_name)
# Construct the table based on the user's permissions
- columns = request.user.config.get(f"tables.{self.table.__name__}.columns")
+ if request.user.is_authenticated:
+ columns = request.user.config.get(f"tables.{self.table.__name__}.columns")
+ else:
+ columns = None
table = self.table(self.queryset, columns=columns)
if 'pk' in table.base_columns and (permissions['change'] or permissions['delete']):
table.columns.show('pk')
@@ -188,6 +193,7 @@ class ObjectListView(View):
return render(request, self.template_name, context)
+ @method_decorator(login_required)
def post(self, request):
# Update the user's table configuration