This commit is contained in:
Pavel Korovin 2016-07-11 20:48:06 +00:00 committed by GitHub
commit cedf4785d9
7 changed files with 89 additions and 56 deletions

View File

@ -1,4 +1,5 @@
from django import forms from django import forms
from django.conf import settings
from django.db.models import Count from django.db.models import Count
from dcim.models import Site, Device, Interface, Rack, IFACE_FF_VIRTUAL from dcim.models import Site, Device, Interface, Rack, IFACE_FF_VIRTUAL
@ -9,6 +10,10 @@ from utilities.forms import (
from .models import Circuit, CircuitType, Provider from .models import Circuit, CircuitType, Provider
url_prefix = ''
if settings.URL_PREFIX.strip('/'):
url_prefix = '/{0}'.format(settings.URL_PREFIX.strip('/'))
# #
# Providers # Providers
@ -82,16 +87,16 @@ class CircuitTypeBulkDeleteForm(ConfirmationForm):
class CircuitForm(forms.ModelForm, BootstrapMixin): class CircuitForm(forms.ModelForm, BootstrapMixin):
site = forms.ModelChoiceField(queryset=Site.objects.all(), widget=forms.Select(attrs={'filter-for': 'rack'})) site = forms.ModelChoiceField(queryset=Site.objects.all(), widget=forms.Select(attrs={'filter-for': 'rack'}))
rack = forms.ModelChoiceField(queryset=Rack.objects.all(), required=False, label='Rack', rack = forms.ModelChoiceField(queryset=Rack.objects.all(), required=False, label='Rack',
widget=APISelect(api_url='/api/dcim/racks/?site_id={{site}}', widget=APISelect(api_url=url_prefix + '/api/dcim/racks/?site_id={{site}}',
attrs={'filter-for': 'device'})) attrs={'filter-for': 'device'}))
device = forms.ModelChoiceField(queryset=Device.objects.all(), required=False, label='Device', device = forms.ModelChoiceField(queryset=Device.objects.all(), required=False, label='Device',
widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?rack_id={{rack}}',
attrs={'filter-for': 'interface'})) attrs={'filter-for': 'interface'}))
livesearch = forms.CharField(required=False, label='Device', widget=Livesearch( livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
query_key='q', query_url='dcim-api:device_list', field_to_update='device') query_key='q', query_url='dcim-api:device_list', field_to_update='device')
) )
interface = forms.ModelChoiceField(queryset=Interface.objects.all(), required=False, label='Interface', interface = forms.ModelChoiceField(queryset=Interface.objects.all(), required=False, label='Interface',
widget=APISelect(api_url='/api/dcim/devices/{{device}}/interfaces/?type=physical', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/{{device}}/interfaces/?type=physical',
disabled_indicator='is_connected')) disabled_indicator='is_connected'))
comments = CommentField() comments = CommentField()

View File

@ -1,6 +1,7 @@
import re import re
from django import forms from django import forms
from django.conf import settings
from django.db.models import Count, Q from django.db.models import Count, Q
from ipam.models import IPAddress from ipam.models import IPAddress
@ -25,6 +26,10 @@ FORM_STATUS_CHOICES += STATUS_CHOICES
DEVICE_BY_PK_RE = '{\d+\}' DEVICE_BY_PK_RE = '{\d+\}'
url_prefix = ''
if settings.URL_PREFIX.strip('/'):
url_prefix = '/{0}'.format(settings.URL_PREFIX.strip('/'))
def get_device_by_name_or_pk(name): def get_device_by_name_or_pk(name):
""" """
@ -105,7 +110,7 @@ class RackGroupFilterForm(forms.Form, BootstrapMixin):
class RackForm(forms.ModelForm, BootstrapMixin): class RackForm(forms.ModelForm, BootstrapMixin):
group = forms.ModelChoiceField(queryset=RackGroup.objects.all(), required=False, label='Group', widget=APISelect( group = forms.ModelChoiceField(queryset=RackGroup.objects.all(), required=False, label='Group', widget=APISelect(
api_url='/api/dcim/rack-groups/?site_id={{site}}', api_url=url_prefix + '/api/dcim/rack-groups/?site_id={{site}}',
)) ))
comments = CommentField() comments = CommentField()
@ -330,18 +335,18 @@ class PlatformBulkDeleteForm(ConfirmationForm):
class DeviceForm(forms.ModelForm, BootstrapMixin): class DeviceForm(forms.ModelForm, BootstrapMixin):
site = forms.ModelChoiceField(queryset=Site.objects.all(), widget=forms.Select(attrs={'filter-for': 'rack'})) site = forms.ModelChoiceField(queryset=Site.objects.all(), widget=forms.Select(attrs={'filter-for': 'rack'}))
rack = forms.ModelChoiceField(queryset=Rack.objects.all(), widget=APISelect( rack = forms.ModelChoiceField(queryset=Rack.objects.all(), widget=APISelect(
api_url='/api/dcim/racks/?site_id={{site}}', api_url=url_prefix + '/api/dcim/racks/?site_id={{site}}',
display_field='display_name', display_field='display_name',
attrs={'filter-for': 'position'} attrs={'filter-for': 'position'}
)) ))
position = forms.TypedChoiceField(required=False, empty_value=None, position = forms.TypedChoiceField(required=False, empty_value=None,
help_text="For multi-U devices, this is the lowest occupied rack unit.", help_text="For multi-U devices, this is the lowest occupied rack unit.",
widget=APISelect(api_url='/api/dcim/racks/{{rack}}/rack-units/?face={{face}}', widget=APISelect(api_url=url_prefix + '/api/dcim/racks/{{rack}}/rack-units/?face={{face}}',
disabled_indicator='device')) disabled_indicator='device'))
manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(), manufacturer = forms.ModelChoiceField(queryset=Manufacturer.objects.all(),
widget=forms.Select(attrs={'filter-for': 'device_type'})) widget=forms.Select(attrs={'filter-for': 'device_type'}))
device_type = forms.ModelChoiceField(queryset=DeviceType.objects.all(), label='Device type', widget=APISelect( device_type = forms.ModelChoiceField(queryset=DeviceType.objects.all(), label='Device type', widget=APISelect(
api_url='/api/dcim/device-types/?manufacturer_id={{manufacturer}}', api_url=url_prefix + '/api/dcim/device-types/?manufacturer_id={{manufacturer}}',
display_field='model' display_field='model'
)) ))
comments = CommentField() comments = CommentField()
@ -614,13 +619,13 @@ class ConsolePortConnectionForm(forms.ModelForm, BootstrapMixin):
rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False, rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
widget=forms.Select(attrs={'filter-for': 'console_server'})) widget=forms.Select(attrs={'filter-for': 'console_server'}))
console_server = forms.ModelChoiceField(queryset=Device.objects.all(), label='Console Server', required=False, console_server = forms.ModelChoiceField(queryset=Device.objects.all(), label='Console Server', required=False,
widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}&is_console_server=True', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?rack_id={{rack}}&is_console_server=True',
attrs={'filter-for': 'cs_port'})) attrs={'filter-for': 'cs_port'}))
livesearch = forms.CharField(required=False, label='Console Server', widget=Livesearch( livesearch = forms.CharField(required=False, label='Console Server', widget=Livesearch(
query_key='q', query_url='dcim-api:device_list', field_to_update='console_server') query_key='q', query_url='dcim-api:device_list', field_to_update='console_server')
) )
cs_port = forms.ModelChoiceField(queryset=ConsoleServerPort.objects.all(), label='Port', cs_port = forms.ModelChoiceField(queryset=ConsoleServerPort.objects.all(), label='Port',
widget=APISelect(api_url='/api/dcim/devices/{{console_server}}/console-server-ports/', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/{{console_server}}/console-server-ports/',
disabled_indicator='connected_console')) disabled_indicator='connected_console'))
class Meta: class Meta:
@ -681,13 +686,13 @@ class ConsoleServerPortConnectionForm(forms.Form, BootstrapMixin):
rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False, rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
widget=forms.Select(attrs={'filter-for': 'device'})) widget=forms.Select(attrs={'filter-for': 'device'}))
device = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False, device = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False,
widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?rack_id={{rack}}',
attrs={'filter-for': 'port'})) attrs={'filter-for': 'port'}))
livesearch = forms.CharField(required=False, label='Device', widget=Livesearch( livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
query_key='q', query_url='dcim-api:device_list', field_to_update='device') query_key='q', query_url='dcim-api:device_list', field_to_update='device')
) )
port = forms.ModelChoiceField(queryset=ConsolePort.objects.all(), label='Port', port = forms.ModelChoiceField(queryset=ConsolePort.objects.all(), label='Port',
widget=APISelect(api_url='/api/dcim/devices/{{device}}/console-ports/', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/{{device}}/console-ports/',
disabled_indicator='cs_port')) disabled_indicator='cs_port'))
connection_status = forms.BooleanField(required=False, initial=CONNECTION_STATUS_CONNECTED, label='Status', connection_status = forms.BooleanField(required=False, initial=CONNECTION_STATUS_CONNECTED, label='Status',
widget=forms.Select(choices=CONNECTION_STATUS_CHOICES)) widget=forms.Select(choices=CONNECTION_STATUS_CHOICES))
@ -810,13 +815,13 @@ class PowerPortConnectionForm(forms.ModelForm, BootstrapMixin):
rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False, rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
widget=forms.Select(attrs={'filter-for': 'pdu'})) widget=forms.Select(attrs={'filter-for': 'pdu'}))
pdu = forms.ModelChoiceField(queryset=Device.objects.all(), label='PDU', required=False, pdu = forms.ModelChoiceField(queryset=Device.objects.all(), label='PDU', required=False,
widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}&is_pdu=True', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?rack_id={{rack}}&is_pdu=True',
attrs={'filter-for': 'power_outlet'})) attrs={'filter-for': 'power_outlet'}))
livesearch = forms.CharField(required=False, label='PDU', widget=Livesearch( livesearch = forms.CharField(required=False, label='PDU', widget=Livesearch(
query_key='q', query_url='dcim-api:device_list', field_to_update='pdu') query_key='q', query_url='dcim-api:device_list', field_to_update='pdu')
) )
power_outlet = forms.ModelChoiceField(queryset=PowerOutlet.objects.all(), label='Outlet', power_outlet = forms.ModelChoiceField(queryset=PowerOutlet.objects.all(), label='Outlet',
widget=APISelect(api_url='/api/dcim/devices/{{pdu}}/power-outlets/', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/{{pdu}}/power-outlets/',
disabled_indicator='connected_port')) disabled_indicator='connected_port'))
class Meta: class Meta:
@ -877,13 +882,13 @@ class PowerOutletConnectionForm(forms.Form, BootstrapMixin):
rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False, rack = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
widget=forms.Select(attrs={'filter-for': 'device'})) widget=forms.Select(attrs={'filter-for': 'device'}))
device = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False, device = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False,
widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack}}', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?rack_id={{rack}}',
attrs={'filter-for': 'port'})) attrs={'filter-for': 'port'}))
livesearch = forms.CharField(required=False, label='Device', widget=Livesearch( livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
query_key='q', query_url='dcim-api:device_list', field_to_update='device') query_key='q', query_url='dcim-api:device_list', field_to_update='device')
) )
port = forms.ModelChoiceField(queryset=PowerPort.objects.all(), label='Port', port = forms.ModelChoiceField(queryset=PowerPort.objects.all(), label='Port',
widget=APISelect(api_url='/api/dcim/devices/{{device}}/power-ports/', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/{{device}}/power-ports/',
disabled_indicator='power_outlet')) disabled_indicator='power_outlet'))
connection_status = forms.BooleanField(required=False, initial=CONNECTION_STATUS_CONNECTED, label='Status', connection_status = forms.BooleanField(required=False, initial=CONNECTION_STATUS_CONNECTED, label='Status',
widget=forms.Select(choices=CONNECTION_STATUS_CHOICES)) widget=forms.Select(choices=CONNECTION_STATUS_CHOICES))
@ -952,13 +957,13 @@ class InterfaceConnectionForm(forms.ModelForm, BootstrapMixin):
rack_b = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False, rack_b = forms.ModelChoiceField(queryset=Rack.objects.all(), label='Rack', required=False,
widget=forms.Select(attrs={'filter-for': 'device_b'})) widget=forms.Select(attrs={'filter-for': 'device_b'}))
device_b = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False, device_b = forms.ModelChoiceField(queryset=Device.objects.all(), label='Device', required=False,
widget=APISelect(api_url='/api/dcim/devices/?rack_id={{rack_b}}', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?rack_id={{rack_b}}',
attrs={'filter-for': 'interface_b'})) attrs={'filter-for': 'interface_b'}))
livesearch = forms.CharField(required=False, label='Device', widget=Livesearch( livesearch = forms.CharField(required=False, label='Device', widget=Livesearch(
query_key='q', query_url='dcim-api:device_list', field_to_update='device_b') query_key='q', query_url='dcim-api:device_list', field_to_update='device_b')
) )
interface_b = forms.ModelChoiceField(queryset=Interface.objects.all(), label='Interface', interface_b = forms.ModelChoiceField(queryset=Interface.objects.all(), label='Interface',
widget=APISelect(api_url='/api/dcim/devices/{{device_b}}/interfaces/?type=physical', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/{{device_b}}/interfaces/?type=physical',
disabled_indicator='is_connected')) disabled_indicator='is_connected'))
class Meta: class Meta:

View File

@ -1,6 +1,7 @@
from netaddr import IPNetwork from netaddr import IPNetwork
from django import forms from django import forms
from django.conf import settings
from django.db.models import Count from django.db.models import Count
from dcim.models import Site, Device, Interface from dcim.models import Site, Device, Interface
@ -16,6 +17,10 @@ from .models import (
FORM_PREFIX_STATUS_CHOICES = (('', '---------'),) + PREFIX_STATUS_CHOICES FORM_PREFIX_STATUS_CHOICES = (('', '---------'),) + PREFIX_STATUS_CHOICES
FORM_VLAN_STATUS_CHOICES = (('', '---------'),) + VLAN_STATUS_CHOICES FORM_VLAN_STATUS_CHOICES = (('', '---------'),) + VLAN_STATUS_CHOICES
url_prefix = ''
if settings.URL_PREFIX.strip('/'):
url_prefix = '/{0}'.format(settings.URL_PREFIX.strip('/'))
# #
# VRFs # VRFs
@ -144,7 +149,7 @@ class PrefixForm(forms.ModelForm, BootstrapMixin):
site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site', site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site',
widget=forms.Select(attrs={'filter-for': 'vlan'})) widget=forms.Select(attrs={'filter-for': 'vlan'}))
vlan = forms.ModelChoiceField(queryset=VLAN.objects.all(), required=False, label='VLAN', vlan = forms.ModelChoiceField(queryset=VLAN.objects.all(), required=False, label='VLAN',
widget=APISelect(api_url='/api/ipam/vlans/?site_id={{site}}', widget=APISelect(api_url=url_prefix + '/api/ipam/vlans/?site_id={{site}}',
display_field='display_name')) display_field='display_name'))
class Meta: class Meta:
@ -270,13 +275,13 @@ class IPAddressForm(forms.ModelForm, BootstrapMixin):
nat_site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site', nat_site = forms.ModelChoiceField(queryset=Site.objects.all(), required=False, label='Site',
widget=forms.Select(attrs={'filter-for': 'nat_device'})) widget=forms.Select(attrs={'filter-for': 'nat_device'}))
nat_device = forms.ModelChoiceField(queryset=Device.objects.all(), required=False, label='Device', nat_device = forms.ModelChoiceField(queryset=Device.objects.all(), required=False, label='Device',
widget=APISelect(api_url='/api/dcim/devices/?site_id={{nat_site}}', widget=APISelect(api_url=url_prefix + '/api/dcim/devices/?site_id={{nat_site}}',
attrs={'filter-for': 'nat_inside'})) attrs={'filter-for': 'nat_inside'}))
livesearch = forms.CharField(required=False, label='IP Address', widget=Livesearch( livesearch = forms.CharField(required=False, label='IP Address', widget=Livesearch(
query_key='q', query_url='ipam-api:ipaddress_list', field_to_update='nat_inside', obj_label='address') query_key='q', query_url='ipam-api:ipaddress_list', field_to_update='nat_inside', obj_label='address')
) )
nat_inside = forms.ModelChoiceField(queryset=IPAddress.objects.all(), required=False, label='NAT (Inside)', nat_inside = forms.ModelChoiceField(queryset=IPAddress.objects.all(), required=False, label='NAT (Inside)',
widget=APISelect(api_url='/api/ipam/ip-addresses/?device_id={{nat_device}}', widget=APISelect(api_url=url_prefix + '/api/ipam/ip-addresses/?device_id={{nat_device}}',
display_field='address')) display_field='address'))
class Meta: class Meta:

View File

@ -32,6 +32,15 @@ SECRET_KEY = ''
# # # #
######################### #########################
# URL prefix if NetBox is served from non-root location, e.g. http://mysite/netbox/
# By default, URL_PREFIX = '/', i.e. NetBox is served from root location
# URL_PREFIX = '/netbox'
# Directory and URL from which static files will be served
# for more info, see https://docs.djangoproject.com/en/1.9/howto/static-files/
# STATIC_ROOT = '/var/www/htdocs/netbox/static/'
# STATIC_URL = '/static/netbox/'
# Specify one or more name and email address tuples representing NetBox administrators. These people will be notified of # Specify one or more name and email address tuples representing NetBox administrators. These people will be notified of
# application errors (assuming correct email settings are provided). # application errors (assuming correct email settings are provided).
ADMINS = [ ADMINS = [

View File

@ -22,7 +22,15 @@ for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
raise ImproperlyConfigured("Mandatory setting {} is missing from configuration.py. Please define it per the " raise ImproperlyConfigured("Mandatory setting {} is missing from configuration.py. Please define it per the "
"documentation.".format(setting)) "documentation.".format(setting))
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Default configurations # Default configurations
URL_PREFIX = getattr(configuration, 'URL_PREFIX', '/')
url_prefix = ''
if URL_PREFIX.strip('/'):
url_prefix = '/{0}'.format(URL_PREFIX.strip('/'))
STATIC_ROOT = getattr(configuration, 'STATIC_ROOT', BASE_DIR + '/static/')
STATIC_URL = getattr(configuration, 'STATIC_URL', '/static' + url_prefix + '/')
ADMINS = getattr(configuration, 'ADMINS', []) ADMINS = getattr(configuration, 'ADMINS', [])
DEBUG = getattr(configuration, 'DEBUG', False) DEBUG = getattr(configuration, 'DEBUG', False)
EMAIL = getattr(configuration, 'EMAIL', {}) EMAIL = getattr(configuration, 'EMAIL', {})
@ -71,8 +79,6 @@ if LDAP_CONFIGURED:
raise ImproperlyConfigured("LDAP authentication has been configured, but django-auth-ldap is not installed. " raise ImproperlyConfigured("LDAP authentication has been configured, but django-auth-ldap is not installed. "
"You can remove netbox/ldap.py to disable LDAP.") "You can remove netbox/ldap.py to disable LDAP.")
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Database # Database
configuration.DATABASE.update({'ENGINE': 'django.db.backends.postgresql'}) configuration.DATABASE.update({'ENGINE': 'django.db.backends.postgresql'})
DATABASES = { DATABASES = {
@ -155,9 +161,7 @@ USE_I18N = True
USE_TZ = True USE_TZ = True
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/ # https://docs.djangoproject.com/en/1.9/howto/static-files/
STATIC_ROOT = BASE_DIR + '/static/'
STATIC_URL = '/static/'
STATICFILES_DIRS = ( STATICFILES_DIRS = (
os.path.join(BASE_DIR, "project-static"), os.path.join(BASE_DIR, "project-static"),
) )
@ -168,9 +172,9 @@ MESSAGE_TAGS = {
} }
# Authentication URLs # Authentication URLs
LOGIN_URL = '/login/' LOGIN_URL = url_prefix + '/login/'
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = url_prefix + '/'
LOGOUT_URL = '/logout/' LOGOUT_URL = url_prefix + '/logout/'
# Secrets # Secrets
SECRETS_MIN_PUBKEY_SIZE = 2048 SECRETS_MIN_PUBKEY_SIZE = 2048
@ -182,7 +186,7 @@ REST_FRAMEWORK = {
# Swagger settings (API docs) # Swagger settings (API docs)
SWAGGER_SETTINGS = { SWAGGER_SETTINGS = {
'base_path': '{}/api/docs'.format(ALLOWED_HOSTS[0]), 'base_path': '{}'.format(ALLOWED_HOSTS[0]) + url_prefix + '/api/docs',
} }

View File

@ -1,3 +1,4 @@
from django.conf import settings
from django.conf.urls import include, url from django.conf.urls import include, url
from django.contrib import admin from django.contrib import admin
from django.views.defaults import page_not_found from django.views.defaults import page_not_found
@ -5,36 +6,40 @@ from django.views.defaults import page_not_found
from views import home, trigger_500 from views import home, trigger_500
from users.views import login, logout from users.views import login, logout
url_prefix = ''
if settings.URL_PREFIX.strip('/'):
url_prefix = '{0}/'.format(settings.URL_PREFIX.strip('/'))
urlpatterns = [ urlpatterns = [
url(r'^{0}'.format(url_prefix),
include([
# Default page
url(r'^$', home, name='home'),
# Default page # Login/logout
url(r'^$', home, name='home'), url(r'^login/$', login, name='login'),
url(r'^logout/$', logout, name='logout'),
# Login/logout # Apps
url(r'^login/$', login, name='login'), url(r'^circuits/', include('circuits.urls', namespace='circuits')),
url(r'^logout/$', logout, name='logout'), 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')),
# Apps # API
url(r'^circuits/', include('circuits.urls', namespace='circuits')), url(r'^api/circuits/', include('circuits.api.urls', namespace='circuits-api')),
url(r'^dcim/', include('dcim.urls', namespace='dcim')), url(r'^api/dcim/', include('dcim.api.urls', namespace='dcim-api')),
url(r'^ipam/', include('ipam.urls', namespace='ipam')), url(r'^api/ipam/', include('ipam.api.urls', namespace='ipam-api')),
url(r'^secrets/', include('secrets.urls', namespace='secrets')), url(r'^api/secrets/', include('secrets.api.urls', namespace='secrets-api')),
url(r'^profile/', include('users.urls', namespace='users')), url(r'^api/docs/', include('rest_framework_swagger.urls')),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
# API # Error testing
url(r'^api/circuits/', include('circuits.api.urls', namespace='circuits-api')), url(r'^404/$', page_not_found),
url(r'^api/dcim/', include('dcim.api.urls', namespace='dcim-api')), url(r'^500/$', trigger_500),
url(r'^api/ipam/', include('ipam.api.urls', namespace='ipam-api')),
url(r'^api/secrets/', include('secrets.api.urls', namespace='secrets-api')),
url(r'^api/docs/', include('rest_framework_swagger.urls')),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
# Error testing
url(r'^404/$', page_not_found),
url(r'^500/$', trigger_500),
# Admin
url(r'^admin/', include(admin.site.urls)),
# Admin
url(r'^admin/', include(admin.site.urls)),
])),
] ]

View File

@ -19,7 +19,7 @@
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" href="/">NetBox</a> <a href="{% url 'home' %}" class="navbar-brand">NetBox</a>
</div> </div>
<div id="navbar" class="navbar-collapse collapse"> <div id="navbar" class="navbar-collapse collapse">
{% if request.user.is_authenticated or not settings.LOGIN_REQUIRED %} {% if request.user.is_authenticated or not settings.LOGIN_REQUIRED %}
@ -263,7 +263,7 @@
<div class="col-xs-4 text-right"> <div class="col-xs-4 text-right">
<p class="text-muted"> <p class="text-muted">
<i class="fa fa-fw fa-book text-primary"></i> <a href="http://netbox.readthedocs.io/" target="_blank">Docs</a> &middot; <i class="fa fa-fw fa-book text-primary"></i> <a href="http://netbox.readthedocs.io/" target="_blank">Docs</a> &middot;
<i class="fa fa-fw fa-cloud text-primary"></i> <a href="/api/docs/">API</a> &middot; <i class="fa fa-fw fa-cloud text-primary"></i> <a href="{% url 'home' %}api/docs/">API</a> &middot;
<i class="fa fa-fw fa-code text-primary"></i> <a href="https://github.com/digitalocean/netbox">Code</a> <i class="fa fa-fw fa-code text-primary"></i> <a href="https://github.com/digitalocean/netbox">Code</a>
</p> </p>
</div> </div>