mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-27 02:48:38 -06:00
Enable serving NetBox from non-root location with URL_PREFIX configuration option
This commit is contained in:
parent
bf35b4121f
commit
627b7fa763
@ -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,9 @@ 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 +86,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()
|
||||||
|
|
||||||
|
@ -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,9 @@ 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 +109,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 +334,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 +618,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 +685,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 +814,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 +881,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 +956,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:
|
||||||
|
@ -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,9 @@ 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 +148,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 +274,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:
|
||||||
|
@ -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 = [
|
||||||
|
@ -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', {})
|
||||||
@ -69,8 +77,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 = {
|
||||||
@ -153,9 +159,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"),
|
||||||
)
|
)
|
||||||
@ -166,9 +170,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
|
||||||
@ -180,7 +184,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',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)),
|
||||||
|
])),
|
||||||
]
|
]
|
||||||
|
@ -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 %}
|
||||||
@ -253,7 +253,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> ·
|
<i class="fa fa-fw fa-book text-primary"></i> <a href="http://netbox.readthedocs.io/" target="_blank">Docs</a> ·
|
||||||
<i class="fa fa-fw fa-cloud text-primary"></i> <a href="/api/docs/">API</a> ·
|
<i class="fa fa-fw fa-cloud text-primary"></i> <a href="{% url 'home' %}api/docs/">API</a> ·
|
||||||
<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>
|
||||||
|
Loading…
Reference in New Issue
Block a user