diff --git a/netbox/circuits/views.py b/netbox/circuits/views.py
index 678105540..2bad5cc75 100644
--- a/netbox/circuits/views.py
+++ b/netbox/circuits/views.py
@@ -7,10 +7,8 @@ from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
)
-from . import forms
-from .filters import CircuitFilter
+from . import filters, forms, tables
from .models import Circuit, CircuitType, Provider
-from .tables import CircuitTable, CircuitTypeTable, ProviderTable
#
@@ -19,7 +17,7 @@ from .tables import CircuitTable, CircuitTypeTable, ProviderTable
class ProviderListView(ObjectListView):
queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
- table = ProviderTable
+ table = tables.ProviderTable
edit_permissions = ['circuits.change_provider', 'circuits.delete_provider']
template_name = 'circuits/provider_list.html'
@@ -52,7 +50,7 @@ class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class ProviderBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'circuits.add_provider'
form = forms.ProviderImportForm
- table = ProviderTable
+ table = tables.ProviderTable
template_name = 'circuits/provider_import.html'
obj_list_url = 'circuits:provider_list'
@@ -88,7 +86,7 @@ class ProviderBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class CircuitTypeListView(ObjectListView):
queryset = CircuitType.objects.annotate(circuit_count=Count('circuits'))
- table = CircuitTypeTable
+ table = tables.CircuitTypeTable
edit_permissions = ['circuits.change_circuittype', 'circuits.delete_circuittype']
template_name = 'circuits/circuittype_list.html'
@@ -114,9 +112,9 @@ class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
class CircuitListView(ObjectListView):
queryset = Circuit.objects.select_related('provider', 'type', 'site')
- filter = CircuitFilter
+ filter = filters.CircuitFilter
filter_form = forms.CircuitFilterForm
- table = CircuitTable
+ table = tables.CircuitTable
edit_permissions = ['circuits.change_circuit', 'circuits.delete_circuit']
template_name = 'circuits/circuit_list.html'
@@ -148,7 +146,7 @@ class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
class CircuitBulkImportView(PermissionRequiredMixin, BulkImportView):
permission_required = 'circuits.add_circuit'
form = forms.CircuitImportForm
- table = CircuitTable
+ table = tables.CircuitTable
template_name = 'circuits/circuit_import.html'
obj_list_url = 'circuits:circuit_list'
diff --git a/netbox/netbox/urls.py b/netbox/netbox/urls.py
index b19d16b73..a7f908544 100644
--- a/netbox/netbox/urls.py
+++ b/netbox/netbox/urls.py
@@ -7,16 +7,22 @@ from users.views import login, logout
urlpatterns = [
+
+ # Default page
url(r'^$', home, name='home'),
+
+ # Login/logout
+ url(r'^login/$', login, name='login'),
+ url(r'^logout/$', logout, name='logout'),
+
+ # Apps
url(r'^circuits/', include('circuits.urls', namespace='circuits')),
url(r'^dcim/', include('dcim.urls', namespace='dcim')),
url(r'^ipam/', include('ipam.urls', namespace='ipam')),
url(r'^secrets/', include('secrets.urls', namespace='secrets')),
url(r'^profile/', include('users.urls', namespace='users')),
- url(r'^login/$', login, name='login'),
- url(r'^logout/$', logout, name='logout'),
-
+ # API
url(r'^api/circuits/', include('circuits.api.urls', namespace='circuits-api')),
url(r'^api/dcim/', include('dcim.api.urls', namespace='dcim-api')),
url(r'^api/ipam/', include('ipam.api.urls', namespace='ipam-api')),
@@ -28,5 +34,7 @@ urlpatterns = [
url(r'^404/$', page_not_found),
url(r'^500/$', trigger_500),
+ # Admin
url(r'^admin/', include(admin.site.urls)),
+
]
diff --git a/netbox/secrets/api/views.py b/netbox/secrets/api/views.py
index ec3dec941..08d1be8f4 100644
--- a/netbox/secrets/api/views.py
+++ b/netbox/secrets/api/views.py
@@ -12,7 +12,8 @@ from rest_framework.views import APIView
from extras.api.renderers import FormlessBrowsableAPIRenderer, FreeRADIUSClientsRenderer
from secrets.filters import SecretFilter
from secrets.models import Secret, SecretRole, UserKey
-from .serializers import SecretRoleSerializer, SecretSerializer
+
+from . import serializers
ERR_USERKEY_MISSING = "No UserKey found for the current user."
@@ -25,7 +26,7 @@ class SecretRoleListView(generics.ListAPIView):
List all secret roles
"""
queryset = SecretRole.objects.all()
- serializer_class = SecretRoleSerializer
+ serializer_class = serializers.SecretRoleSerializer
class SecretRoleDetailView(generics.RetrieveAPIView):
@@ -33,7 +34,7 @@ class SecretRoleDetailView(generics.RetrieveAPIView):
Retrieve a single secret role
"""
queryset = SecretRole.objects.all()
- serializer_class = SecretRoleSerializer
+ serializer_class = serializers.SecretRoleSerializer
class SecretListView(generics.GenericAPIView):
@@ -42,7 +43,7 @@ class SecretListView(generics.GenericAPIView):
"""
queryset = Secret.objects.select_related('device__primary_ip', 'role')\
.prefetch_related('role__users', 'role__groups')
- serializer_class = SecretSerializer
+ serializer_class = serializers.SecretSerializer
filter_class = SecretFilter
renderer_classes = [FormlessBrowsableAPIRenderer, JSONRenderer, FreeRADIUSClientsRenderer]
@@ -87,7 +88,7 @@ class SecretDetailView(generics.GenericAPIView):
"""
queryset = Secret.objects.select_related('device__primary_ip', 'role')\
.prefetch_related('role__users', 'role__groups')
- serializer_class = SecretSerializer
+ serializer_class = serializers.SecretSerializer
renderer_classes = [FormlessBrowsableAPIRenderer, JSONRenderer, FreeRADIUSClientsRenderer]
def get(self, request, pk, private_key=None):
diff --git a/netbox/secrets/forms.py b/netbox/secrets/forms.py
index 1b107d863..478381b45 100644
--- a/netbox/secrets/forms.py
+++ b/netbox/secrets/forms.py
@@ -6,6 +6,7 @@ from django.db.models import Count
from dcim.models import Device
from utilities.forms import BootstrapMixin, BulkImportForm, ConfirmationForm, CSVDataField
+
from .models import Secret, SecretRole, UserKey
@@ -133,4 +134,3 @@ class UserKeyForm(forms.ModelForm, BootstrapMixin):
class ActivateUserKeyForm(forms.Form):
_selected_action = forms.ModelMultipleChoiceField(queryset=UserKey.objects.all(), label='User Keys')
secret_key = forms.CharField(label='Your private key', widget=forms.Textarea(attrs={'class': 'vLargeTextField'}))
-
diff --git a/netbox/secrets/models.py b/netbox/secrets/models.py
index cc6ab737f..bab0015c3 100644
--- a/netbox/secrets/models.py
+++ b/netbox/secrets/models.py
@@ -11,6 +11,7 @@ from django.db import models
from django.utils.encoding import force_bytes
from dcim.models import Device
+
from .hashers import SecretValidationHasher
diff --git a/netbox/secrets/tables.py b/netbox/secrets/tables.py
index 6c40c2e0e..caee8a50b 100644
--- a/netbox/secrets/tables.py
+++ b/netbox/secrets/tables.py
@@ -5,7 +5,9 @@ from .models import SecretRole, Secret
SECRETROLE_EDIT_LINK = """
-{% if perms.secrets.change_secretrole %}Edit{% endif %}
+{% if perms.secrets.change_secretrole %}
+ Edit
+{% endif %}
"""
diff --git a/netbox/secrets/urls.py b/netbox/secrets/urls.py
index 29daed109..b6751617d 100644
--- a/netbox/secrets/urls.py
+++ b/netbox/secrets/urls.py
@@ -2,6 +2,7 @@ from django.conf.urls import url
from . import views
+
urlpatterns = [
# Secret roles
diff --git a/netbox/secrets/views.py b/netbox/secrets/views.py
index c964f97ac..a565785a4 100644
--- a/netbox/secrets/views.py
+++ b/netbox/secrets/views.py
@@ -8,14 +8,11 @@ from django.shortcuts import get_object_or_404, redirect, render
from django.utils.decorators import method_decorator
from dcim.models import Device
-from utilities.views import BulkEditView, BulkDeleteView, ObjectListView, ObjectEditView, ObjectDeleteView
+from utilities.views import BulkDeleteView, BulkEditView, ObjectDeleteView, ObjectEditView, ObjectListView
+from . import filters, forms, tables
from .decorators import userkey_required
-from .filters import SecretFilter
-from .forms import SecretRoleForm, SecretRoleBulkDeleteForm, SecretForm, SecretImportForm, SecretBulkEditForm,\
- SecretBulkDeleteForm, SecretFilterForm
from .models import SecretRole, Secret, UserKey
-from .tables import SecretRoleTable, SecretTable
#
@@ -24,7 +21,7 @@ from .tables import SecretRoleTable, SecretTable
class SecretRoleListView(ObjectListView):
queryset = SecretRole.objects.annotate(secret_count=Count('secrets'))
- table = SecretRoleTable
+ table = tables.SecretRoleTable
edit_permissions = ['secrets.change_secretrole', 'secrets.delete_secretrole']
template_name = 'secrets/secretrole_list.html'
@@ -32,7 +29,7 @@ class SecretRoleListView(ObjectListView):
class SecretRoleEditView(PermissionRequiredMixin, ObjectEditView):
permission_required = 'secrets.change_secretrole'
model = SecretRole
- form_class = SecretRoleForm
+ form_class = forms.SecretRoleForm
success_url = 'secrets:secretrole_list'
cancel_url = 'secrets:secretrole_list'
@@ -40,7 +37,7 @@ class SecretRoleEditView(PermissionRequiredMixin, ObjectEditView):
class SecretRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'secrets.delete_secretrole'
cls = SecretRole
- form = SecretRoleBulkDeleteForm
+ form = forms.SecretRoleBulkDeleteForm
default_redirect_url = 'secrets:secretrole_list'
@@ -51,9 +48,9 @@ class SecretRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
@method_decorator(login_required, name='dispatch')
class SecretListView(ObjectListView):
queryset = Secret.objects.select_related('role').prefetch_related('device')
- filter = SecretFilter
- filter_form = SecretFilterForm
- table = SecretTable
+ filter = filters.SecretFilter
+ filter_form = forms.SecretFilterForm
+ table = tables.SecretTable
edit_permissions = ['secrets.change_secret', 'secrets.delete_secret']
template_name = 'secrets/secret_list.html'
@@ -79,7 +76,7 @@ def secret_add(request, pk):
uk = UserKey.objects.get(user=request.user)
if request.method == 'POST':
- form = SecretForm(request.POST, instance=secret)
+ form = forms.SecretForm(request.POST, instance=secret)
if form.is_valid():
# Retrieve the master key from the current user's UserKey
@@ -101,7 +98,7 @@ def secret_add(request, pk):
return redirect('secrets:secret', pk=secret.pk)
else:
- form = SecretForm(instance=secret)
+ form = forms.SecretForm(instance=secret)
return render(request, 'secrets/secret_edit.html', {
'secret': secret,
@@ -118,7 +115,7 @@ def secret_edit(request, pk):
uk = UserKey.objects.get(user=request.user)
if request.method == 'POST':
- form = SecretForm(request.POST, instance=secret)
+ form = forms.SecretForm(request.POST, instance=secret)
if form.is_valid():
# Re-encrypt the Secret if a plaintext has been specified.
@@ -143,7 +140,7 @@ def secret_edit(request, pk):
return redirect('secrets:secret', pk=secret.pk)
else:
- form = SecretForm(instance=secret)
+ form = forms.SecretForm(instance=secret)
return render(request, 'secrets/secret_edit.html', {
'secret': secret,
@@ -165,7 +162,7 @@ def secret_import(request):
uk = UserKey.objects.get(user=request.user)
if request.method == 'POST':
- form = SecretImportForm(request.POST)
+ form = forms.SecretImportForm(request.POST)
if form.is_valid():
new_secrets = []
@@ -183,7 +180,7 @@ def secret_import(request):
secret.save()
new_secrets.append(secret)
- table = SecretTable(new_secrets)
+ table = tables.SecretTable(new_secrets)
messages.success(request, "Imported {} new secrets".format(len(new_secrets)))
return render(request, 'import_success.html', {
@@ -194,7 +191,7 @@ def secret_import(request):
form.add_error('csv', "Record {}: {}".format(len(new_secrets) + 1, e.__cause__))
else:
- form = SecretImportForm()
+ form = forms.SecretImportForm()
return render(request, 'secrets/secret_import.html', {
'form': form,
@@ -205,7 +202,7 @@ def secret_import(request):
class SecretBulkEditView(PermissionRequiredMixin, BulkEditView):
permission_required = 'secrets.change_secret'
cls = Secret
- form = SecretBulkEditForm
+ form = forms.SecretBulkEditForm
template_name = 'secrets/secret_bulk_edit.html'
default_redirect_url = 'secrets:secret_list'
@@ -223,5 +220,5 @@ class SecretBulkEditView(PermissionRequiredMixin, BulkEditView):
class SecretBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
permission_required = 'secrets.delete_secret'
cls = Secret
- form = SecretBulkDeleteForm
+ form = forms.SecretBulkDeleteForm
default_redirect_url = 'secrets:secret_list'
diff --git a/netbox/users/admin.py b/netbox/users/admin.py
deleted file mode 100644
index 8c38f3f3d..000000000
--- a/netbox/users/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/netbox/users/tests.py b/netbox/users/tests.py
deleted file mode 100644
index 7ce503c2d..000000000
--- a/netbox/users/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/netbox/users/urls.py b/netbox/users/urls.py
index 0f86b2107..4e38050f1 100644
--- a/netbox/users/urls.py
+++ b/netbox/users/urls.py
@@ -2,9 +2,13 @@ from django.conf.urls import url
from . import views
+
urlpatterns = [
+
+ # User profiles
url(r'^profile/$', views.profile, name='profile'),
url(r'^profile/password/$', views.change_password, name='change_password'),
url(r'^profile/user-key/$', views.userkey, name='userkey'),
url(r'^profile/user-key/edit/$', views.userkey_edit, name='userkey_edit'),
+
]
diff --git a/netbox/users/views.py b/netbox/users/views.py
index d2274071c..0337833b8 100644
--- a/netbox/users/views.py
+++ b/netbox/users/views.py
@@ -9,6 +9,7 @@ from django.utils.http import is_safe_url
from secrets.forms import UserKeyForm
from secrets.models import UserKey
+
from .forms import LoginForm, PasswordChangeForm
diff --git a/netbox/utilities/fields.py b/netbox/utilities/fields.py
index 5f93612d3..017ceb275 100644
--- a/netbox/utilities/fields.py
+++ b/netbox/utilities/fields.py
@@ -3,7 +3,6 @@ from django.db import models
class NullableCharField(models.CharField):
description = "Stores empty values as NULL rather than ''"
- #__metaclass__ = models.SubfieldBase
def to_python(self, value):
if isinstance(value, models.CharField):
diff --git a/netbox/utilities/views.py b/netbox/utilities/views.py
index 56e0d7e6a..e3333997e 100644
--- a/netbox/utilities/views.py
+++ b/netbox/utilities/views.py
@@ -1,8 +1,10 @@
+from django_tables2 import RequestConfig
+
from django.conf import settings
from django.contrib import messages
from django.contrib.admin.views.decorators import staff_member_required
from django.contrib.contenttypes.models import ContentType
-from django.core.urlresolvers import reverse, NoReverseMatch
+from django.core.urlresolvers import reverse
from django.db import transaction, IntegrityError
from django.db.models import ProtectedError
from django.http import HttpResponseRedirect
@@ -12,12 +14,11 @@ from django.utils.decorators import method_decorator
from django.utils.http import is_safe_url
from django.views.generic import View
-from django_tables2 import RequestConfig
+from extras.models import ExportTemplate
from .error_handlers import handle_protectederror
from .forms import ConfirmationForm
from .paginator import EnhancedPaginator
-from extras.models import ExportTemplate
class ObjectListView(View):
@@ -45,7 +46,8 @@ class ObjectListView(View):
filename='netbox_{}'.format(self.queryset.model._meta.verbose_name_plural))
return response
except TemplateSyntaxError:
- messages.error(request, "There was an error rendering the selected export template ({}).".format(et.name))
+ messages.error(request, "There was an error rendering the selected export template ({})."
+ .format(et.name))
# Attempt to redirect automatically if the query returns a single result
if self.redirect_on_single_result and self.queryset.count() == 1: