mirror of
				https://github.com/netbox-community/netbox.git
				synced 2024-05-10 07:54:54 +00:00 
			
		
		
		
	Merge pull request #3069 from digitalocean/2647-caching
intial work on #2647 - caching
This commit is contained in:
		@@ -1,6 +1,7 @@
 | 
			
		||||
sudo: required
 | 
			
		||||
services:
 | 
			
		||||
  - postgresql
 | 
			
		||||
  - redis-server
 | 
			
		||||
addons:
 | 
			
		||||
  postgresql: "9.4"
 | 
			
		||||
language: python
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,10 @@ django-filter
 | 
			
		||||
# https://github.com/django-mptt/django-mptt
 | 
			
		||||
django-mptt
 | 
			
		||||
 | 
			
		||||
# Django caching using Redis
 | 
			
		||||
# https://github.com/niwinz/django-redis
 | 
			
		||||
django-redis
 | 
			
		||||
 | 
			
		||||
# Abstraction models for rendering and paginating HTML tables
 | 
			
		||||
# https://github.com/jieter/django-tables2
 | 
			
		||||
django-tables2
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,12 @@
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import permission_required
 | 
			
		||||
from django.contrib.auth.mixins import PermissionRequiredMixin
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.db.models import Count
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
 | 
			
		||||
from extras.models import Graph, GRAPH_TYPE_PROVIDER
 | 
			
		||||
@@ -32,6 +35,7 @@ class ProviderListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class ProviderView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'circuits.view_provider'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, slug):
 | 
			
		||||
 | 
			
		||||
        provider = get_object_or_404(Provider, slug=slug)
 | 
			
		||||
@@ -147,6 +151,7 @@ class CircuitListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class CircuitView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'circuits.view_circuit'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        circuit = get_object_or_404(Circuit.objects.select_related('provider', 'type', 'tenant__group'), pk=pk)
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,8 @@ from django.urls import reverse
 | 
			
		||||
from django.utils.html import escape
 | 
			
		||||
from django.utils.http import is_safe_url
 | 
			
		||||
from django.utils.safestring import mark_safe
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
 | 
			
		||||
from circuits.models import Circuit
 | 
			
		||||
@@ -195,6 +197,7 @@ class SiteListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class SiteView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_site'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, slug):
 | 
			
		||||
 | 
			
		||||
        site = get_object_or_404(Site.objects.select_related('region', 'tenant__group'), slug=slug)
 | 
			
		||||
@@ -353,6 +356,7 @@ class RackElevationListView(PermissionRequiredMixin, View):
 | 
			
		||||
    """
 | 
			
		||||
    permission_required = 'dcim.view_rack'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        racks = Rack.objects.select_related(
 | 
			
		||||
@@ -392,6 +396,7 @@ class RackElevationListView(PermissionRequiredMixin, View):
 | 
			
		||||
class RackView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_rack'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        rack = get_object_or_404(Rack.objects.select_related('site__region', 'tenant__group', 'group', 'role'), pk=pk)
 | 
			
		||||
@@ -570,6 +575,7 @@ class DeviceTypeListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class DeviceTypeView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_devicetype'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        devicetype = get_object_or_404(DeviceType, pk=pk)
 | 
			
		||||
@@ -910,6 +916,7 @@ class DeviceListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class DeviceView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_device'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device = get_object_or_404(Device.objects.select_related(
 | 
			
		||||
@@ -991,6 +998,7 @@ class DeviceView(PermissionRequiredMixin, View):
 | 
			
		||||
class DeviceInventoryView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_device'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device = get_object_or_404(Device, pk=pk)
 | 
			
		||||
@@ -1012,6 +1020,7 @@ class DeviceInventoryView(PermissionRequiredMixin, View):
 | 
			
		||||
class DeviceStatusView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = ('dcim.view_device', 'dcim.napalm_read')
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device = get_object_or_404(Device, pk=pk)
 | 
			
		||||
@@ -1025,6 +1034,7 @@ class DeviceStatusView(PermissionRequiredMixin, View):
 | 
			
		||||
class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = ('dcim.view_device', 'dcim.napalm_read')
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device = get_object_or_404(Device, pk=pk)
 | 
			
		||||
@@ -1042,6 +1052,7 @@ class DeviceLLDPNeighborsView(PermissionRequiredMixin, View):
 | 
			
		||||
class DeviceConfigView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = ('dcim.view_device', 'dcim.napalm_read')
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device = get_object_or_404(Device, pk=pk)
 | 
			
		||||
@@ -1279,6 +1290,7 @@ class PowerOutletBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 | 
			
		||||
class InterfaceView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_interface'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        interface = get_object_or_404(Interface, pk=pk)
 | 
			
		||||
@@ -1499,6 +1511,7 @@ class DeviceBayDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 | 
			
		||||
class DeviceBayPopulateView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.change_devicebay'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device_bay = get_object_or_404(DeviceBay, pk=pk)
 | 
			
		||||
@@ -1533,6 +1546,7 @@ class DeviceBayPopulateView(PermissionRequiredMixin, View):
 | 
			
		||||
class DeviceBayDepopulateView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.change_devicebay'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device_bay = get_object_or_404(DeviceBay, pk=pk)
 | 
			
		||||
@@ -1672,6 +1686,7 @@ class CableListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class CableView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_cable'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        cable = get_object_or_404(Cable, pk=pk)
 | 
			
		||||
@@ -1687,6 +1702,7 @@ class CableTraceView(PermissionRequiredMixin, View):
 | 
			
		||||
    """
 | 
			
		||||
    permission_required = 'dcim.view_cable'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, model, pk):
 | 
			
		||||
 | 
			
		||||
        obj = get_object_or_404(model, pk=pk)
 | 
			
		||||
@@ -1726,6 +1742,7 @@ class CableCreateView(PermissionRequiredMixin, GetReturnURLMixin, View):
 | 
			
		||||
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, *args, **kwargs):
 | 
			
		||||
 | 
			
		||||
        # Parse initial data manually to avoid setting field values as lists
 | 
			
		||||
@@ -2042,6 +2059,7 @@ class VirtualChassisCreateView(PermissionRequiredMixin, View):
 | 
			
		||||
class VirtualChassisEditView(PermissionRequiredMixin, GetReturnURLMixin, View):
 | 
			
		||||
    permission_required = 'dcim.change_virtualchassis'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        virtual_chassis = get_object_or_404(VirtualChassis, pk=pk)
 | 
			
		||||
@@ -2110,6 +2128,7 @@ class VirtualChassisDeleteView(PermissionRequiredMixin, ObjectDeleteView):
 | 
			
		||||
class VirtualChassisAddMemberView(PermissionRequiredMixin, GetReturnURLMixin, View):
 | 
			
		||||
    permission_required = 'dcim.change_virtualchassis'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        virtual_chassis = get_object_or_404(VirtualChassis, pk=pk)
 | 
			
		||||
@@ -2164,6 +2183,7 @@ class VirtualChassisAddMemberView(PermissionRequiredMixin, GetReturnURLMixin, Vi
 | 
			
		||||
class VirtualChassisRemoveMemberView(PermissionRequiredMixin, GetReturnURLMixin, View):
 | 
			
		||||
    permission_required = 'dcim.change_virtualchassis'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        device = get_object_or_404(Device, pk=pk, virtual_chassis__isnull=False)
 | 
			
		||||
@@ -2227,6 +2247,7 @@ class PowerPanelListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class PowerPanelView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_powerpanel'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        powerpanel = get_object_or_404(PowerPanel.objects.select_related('site', 'rack_group'), pk=pk)
 | 
			
		||||
@@ -2296,6 +2317,7 @@ class PowerFeedListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class PowerFeedView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'dcim.view_powerfeed'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        powerfeed = get_object_or_404(PowerFeed.objects.select_related('power_panel', 'rack'), pk=pk)
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,8 @@ from django.db.models import Count, Q
 | 
			
		||||
from django.http import Http404
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.utils.safestring import mark_safe
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
from django_tables2 import RequestConfig
 | 
			
		||||
 | 
			
		||||
@@ -41,6 +43,7 @@ class TagListView(ObjectListView):
 | 
			
		||||
 | 
			
		||||
class TagView(View):
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, slug):
 | 
			
		||||
 | 
			
		||||
        tag = get_object_or_404(Tag, slug=slug)
 | 
			
		||||
@@ -108,6 +111,7 @@ class ConfigContextListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class ConfigContextView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'extras.view_configcontext'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        configcontext = get_object_or_404(ConfigContext, pk=pk)
 | 
			
		||||
@@ -155,6 +159,7 @@ class ObjectConfigContextView(View):
 | 
			
		||||
    object_class = None
 | 
			
		||||
    base_template = None
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        obj = get_object_or_404(self.object_class, pk=pk)
 | 
			
		||||
@@ -187,6 +192,7 @@ class ObjectChangeListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class ObjectChangeView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'extras.view_objectchange'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        objectchange = get_object_or_404(ObjectChange, pk=pk)
 | 
			
		||||
@@ -209,6 +215,7 @@ class ObjectChangeLogView(View):
 | 
			
		||||
    Present a history of changes made to a particular object.
 | 
			
		||||
    """
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, model, **kwargs):
 | 
			
		||||
 | 
			
		||||
        # Get object my model and kwargs (e.g. slug='foo')
 | 
			
		||||
@@ -282,6 +289,7 @@ class ReportListView(PermissionRequiredMixin, View):
 | 
			
		||||
    """
 | 
			
		||||
    permission_required = 'extras.view_reportresult'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        reports = get_reports()
 | 
			
		||||
@@ -306,6 +314,7 @@ class ReportView(PermissionRequiredMixin, View):
 | 
			
		||||
    """
 | 
			
		||||
    permission_required = 'extras.view_reportresult'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, name):
 | 
			
		||||
 | 
			
		||||
        # Retrieve the Report by "<module>.<report>"
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,8 @@ from django.conf import settings
 | 
			
		||||
from django.contrib.auth.mixins import PermissionRequiredMixin
 | 
			
		||||
from django.db.models import Count, Q
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
from django_tables2 import RequestConfig
 | 
			
		||||
 | 
			
		||||
@@ -125,6 +127,7 @@ class VRFListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class VRFView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_vrf'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        vrf = get_object_or_404(VRF.objects.all(), pk=pk)
 | 
			
		||||
@@ -319,6 +322,7 @@ class AggregateListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class AggregateView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_aggregate'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        aggregate = get_object_or_404(Aggregate, pk=pk)
 | 
			
		||||
@@ -456,6 +460,7 @@ class PrefixListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class PrefixView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_prefix'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        prefix = get_object_or_404(Prefix.objects.select_related(
 | 
			
		||||
@@ -500,6 +505,7 @@ class PrefixView(PermissionRequiredMixin, View):
 | 
			
		||||
class PrefixPrefixesView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_prefix'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        prefix = get_object_or_404(Prefix.objects.all(), pk=pk)
 | 
			
		||||
@@ -543,6 +549,7 @@ class PrefixPrefixesView(PermissionRequiredMixin, View):
 | 
			
		||||
class PrefixIPAddressesView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_prefix'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        prefix = get_object_or_404(Prefix.objects.all(), pk=pk)
 | 
			
		||||
@@ -643,6 +650,7 @@ class IPAddressListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class IPAddressView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_ipaddress'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        ipaddress = get_object_or_404(IPAddress.objects.select_related('vrf__tenant', 'tenant'), pk=pk)
 | 
			
		||||
@@ -726,6 +734,7 @@ class IPAddressAssignView(PermissionRequiredMixin, View):
 | 
			
		||||
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        form = forms.IPAddressAssignForm()
 | 
			
		||||
@@ -838,6 +847,7 @@ class VLANGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 | 
			
		||||
class VLANGroupVLANsView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_vlangroup'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        vlan_group = get_object_or_404(VLANGroup.objects.all(), pk=pk)
 | 
			
		||||
@@ -888,6 +898,7 @@ class VLANListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class VLANView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_vlan'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        vlan = get_object_or_404(VLAN.objects.select_related(
 | 
			
		||||
@@ -906,6 +917,7 @@ class VLANView(PermissionRequiredMixin, View):
 | 
			
		||||
class VLANMembersView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_vlan'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        vlan = get_object_or_404(VLAN.objects.all(), pk=pk)
 | 
			
		||||
@@ -984,6 +996,7 @@ class ServiceListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class ServiceView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'ipam.view_service'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        service = get_object_or_404(Service, pk=pk)
 | 
			
		||||
 
 | 
			
		||||
@@ -25,6 +25,16 @@ DATABASE = {
 | 
			
		||||
# https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-SECRET_KEY
 | 
			
		||||
SECRET_KEY = ''
 | 
			
		||||
 | 
			
		||||
# Redis database settings. The Redis database is used for caching and background processing such as webhooks
 | 
			
		||||
REDIS = {
 | 
			
		||||
    'HOST': 'localhost',
 | 
			
		||||
    'PORT': 6379,
 | 
			
		||||
    'PASSWORD': '',
 | 
			
		||||
    'DATABASE': 0,
 | 
			
		||||
    'DEFAULT_TIMEOUT': 300,
 | 
			
		||||
    'SSL': False,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#########################
 | 
			
		||||
#                       #
 | 
			
		||||
@@ -50,6 +60,18 @@ BANNER_LOGIN = ''
 | 
			
		||||
# BASE_PATH = 'netbox/'
 | 
			
		||||
BASE_PATH = ''
 | 
			
		||||
 | 
			
		||||
# The fraction of entries that are culled when CACHE_MAX_ENTRIES is reached. The actual ratio is 1 / CACHE_CULL_FREQUENCY,
 | 
			
		||||
# so set CACHE_CULL_FREQUENCY to 2 to cull half the entries when CACHE_MAX_ENTRIES is reached. This setting should be an
 | 
			
		||||
# integer and defaults to 3
 | 
			
		||||
CACHE_CULL_FREQUENCY = 3
 | 
			
		||||
 | 
			
		||||
# Max number of entries (unique pages) to store in the cache at a time.
 | 
			
		||||
CACHE_MAX_ENTRIES = 300
 | 
			
		||||
 | 
			
		||||
# Cache timeout in seconds. Set to `None` to enforce an infinate timeout. Set to 0 to dissable caching by immediatly
 | 
			
		||||
# expiring keys. Defaults to 900 (15 minutes)
 | 
			
		||||
CACHE_TIMEOUT = 900
 | 
			
		||||
 | 
			
		||||
# Maximum number of days to retain logged changes. Set to 0 to retain changes indefinitely. (Default: 90)
 | 
			
		||||
CHANGELOG_RETENTION = 90
 | 
			
		||||
 | 
			
		||||
@@ -133,16 +155,6 @@ PAGINATE_COUNT = 50
 | 
			
		||||
# prefer IPv4 instead.
 | 
			
		||||
PREFER_IPV4 = False
 | 
			
		||||
 | 
			
		||||
# Redis database settings (optional). A Redis database is required only if the webhooks backend is enabled.
 | 
			
		||||
REDIS = {
 | 
			
		||||
    'HOST': 'localhost',
 | 
			
		||||
    'PORT': 6379,
 | 
			
		||||
    'PASSWORD': '',
 | 
			
		||||
    'DATABASE': 0,
 | 
			
		||||
    'DEFAULT_TIMEOUT': 300,
 | 
			
		||||
    'SSL': False,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# The file path where custom reports will be stored. A trailing slash is not needed. Note that the default value of
 | 
			
		||||
# this setting is derived from the installed location.
 | 
			
		||||
# REPORTS_ROOT = '/opt/netbox/netbox/reports'
 | 
			
		||||
 
 | 
			
		||||
@@ -28,7 +28,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
			
		||||
 | 
			
		||||
# Import required configuration parameters
 | 
			
		||||
ALLOWED_HOSTS = DATABASE = SECRET_KEY = None
 | 
			
		||||
for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY']:
 | 
			
		||||
for setting in ['ALLOWED_HOSTS', 'DATABASE', 'SECRET_KEY', 'REDIS']:
 | 
			
		||||
    try:
 | 
			
		||||
        globals()[setting] = getattr(configuration, setting)
 | 
			
		||||
    except AttributeError:
 | 
			
		||||
@@ -44,6 +44,9 @@ BANNER_TOP = getattr(configuration, 'BANNER_TOP', '')
 | 
			
		||||
BASE_PATH = getattr(configuration, 'BASE_PATH', '')
 | 
			
		||||
if BASE_PATH:
 | 
			
		||||
    BASE_PATH = BASE_PATH.strip('/') + '/'  # Enforce trailing slash only
 | 
			
		||||
CACHE_TIMEOUT = getattr(configuration, 'CACHE_TIMEOUT', 900)
 | 
			
		||||
CACHE_MAX_ENTRIES = getattr(configuration, 'CACHE_MAX_ENTRIES', 300)
 | 
			
		||||
CACHE_CULL_FREQUENCY = getattr(configuration, 'CACHE_CULL_FREQUENCY', 3)
 | 
			
		||||
CHANGELOG_RETENTION = getattr(configuration, 'CHANGELOG_RETENTION', 90)
 | 
			
		||||
CORS_ORIGIN_ALLOW_ALL = getattr(configuration, 'CORS_ORIGIN_ALLOW_ALL', False)
 | 
			
		||||
CORS_ORIGIN_REGEX_WHITELIST = getattr(configuration, 'CORS_ORIGIN_REGEX_WHITELIST', [])
 | 
			
		||||
@@ -157,6 +160,7 @@ INSTALLED_APPS = [
 | 
			
		||||
    'django.contrib.staticfiles',
 | 
			
		||||
    'django.contrib.humanize',
 | 
			
		||||
    'corsheaders',
 | 
			
		||||
    'django_redis',
 | 
			
		||||
    'debug_toolbar',
 | 
			
		||||
    'django_filters',
 | 
			
		||||
    'django_tables2',
 | 
			
		||||
@@ -218,6 +222,31 @@ TEMPLATES = [
 | 
			
		||||
    },
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
# Caching
 | 
			
		||||
if REDIS_SSL:
 | 
			
		||||
    REDIS_CACHE_CON_STRING = 'rediss://'
 | 
			
		||||
else:
 | 
			
		||||
    REDIS_CACHE_CON_STRING = 'redis://'
 | 
			
		||||
 | 
			
		||||
if REDIS_PASSWORD:
 | 
			
		||||
    REDIS_CACHE_CON_STRING = '{}@{}'.format(REDIS_PASSWORD, REDIS_CACHE_CON_STRING)
 | 
			
		||||
 | 
			
		||||
REDIS_CACHE_CON_STRING = '{}{}:{}/{}'.format(REDIS_CACHE_CON_STRING, REDIS_HOST, REDIS_PORT, REDIS_DATABASE)
 | 
			
		||||
CACHE_BACKEND = 'django_redis.cache.RedisCache'
 | 
			
		||||
 | 
			
		||||
CACHES = {
 | 
			
		||||
    "default": {
 | 
			
		||||
        "BACKEND": CACHE_BACKEND,
 | 
			
		||||
        "LOCATION": REDIS_CACHE_CON_STRING,
 | 
			
		||||
        'TIMEOUT': CACHE_TIMEOUT,
 | 
			
		||||
        "OPTIONS": {
 | 
			
		||||
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
 | 
			
		||||
            "MAX_ENTRIES": CACHE_MAX_ENTRIES,
 | 
			
		||||
            "CULL_FREQUENCY": CACHE_CULL_FREQUENCY
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# WSGI
 | 
			
		||||
WSGI_APPLICATION = 'netbox.wsgi.application'
 | 
			
		||||
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,10 @@
 | 
			
		||||
from collections import OrderedDict
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.db.models import Count, F
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
from rest_framework.response import Response
 | 
			
		||||
from rest_framework.reverse import reverse
 | 
			
		||||
@@ -160,6 +163,7 @@ SEARCH_TYPES = OrderedDict((
 | 
			
		||||
class HomeView(View):
 | 
			
		||||
    template_name = 'home.html'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        connected_consoleports = ConsolePort.objects.filter(
 | 
			
		||||
@@ -219,6 +223,7 @@ class HomeView(View):
 | 
			
		||||
 | 
			
		||||
class SearchView(View):
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        # No query
 | 
			
		||||
@@ -272,6 +277,7 @@ class APIRootView(APIView):
 | 
			
		||||
    def get_view_name(self):
 | 
			
		||||
        return "API Root"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, format=None):
 | 
			
		||||
 | 
			
		||||
        return Response(OrderedDict((
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import base64
 | 
			
		||||
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import permission_required, login_required
 | 
			
		||||
from django.contrib.auth.mixins import PermissionRequiredMixin
 | 
			
		||||
@@ -7,6 +8,7 @@ from django.db.models import Count
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
 | 
			
		||||
from dcim.models import Device
 | 
			
		||||
@@ -80,6 +82,7 @@ class SecretListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class SecretView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'secrets.view_secret'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        secret = get_object_or_404(Secret, pk=pk)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib.auth.mixins import PermissionRequiredMixin
 | 
			
		||||
from django.db.models import Count
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
 | 
			
		||||
from circuits.models import Circuit
 | 
			
		||||
@@ -66,6 +69,7 @@ class TenantListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class TenantView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'tenancy.view_tenant'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, slug):
 | 
			
		||||
 | 
			
		||||
        tenant = get_object_or_404(Tenant, slug=slug)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ from django.contrib.contenttypes.models import ContentType
 | 
			
		||||
from django.core.exceptions import ObjectDoesNotExist
 | 
			
		||||
from django.db.models import ManyToManyField
 | 
			
		||||
from django.http import Http404
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from rest_framework.exceptions import APIException
 | 
			
		||||
from rest_framework.permissions import BasePermission
 | 
			
		||||
from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
 | 
			
		||||
@@ -248,6 +250,20 @@ class ModelViewSet(_ModelViewSet):
 | 
			
		||||
        # Fall back to the hard-coded serializer class
 | 
			
		||||
        return self.serializer_class
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def list(self, *args, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Call to super to allow for caching
 | 
			
		||||
        """
 | 
			
		||||
        return super().list(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def retrieve(self, *args, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
        Call to super to allow for caching
 | 
			
		||||
        """
 | 
			
		||||
        return super().retrieve(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class FieldChoicesViewSet(ViewSet):
 | 
			
		||||
    """
 | 
			
		||||
@@ -284,9 +300,11 @@ class FieldChoicesViewSet(ViewSet):
 | 
			
		||||
                        })
 | 
			
		||||
                self._fields[key] = choices
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def list(self, request):
 | 
			
		||||
        return Response(self._fields)
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def retrieve(self, request, pk):
 | 
			
		||||
        if pk not in self._fields:
 | 
			
		||||
            raise Http404
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,8 @@ from django.urls import reverse
 | 
			
		||||
from django.utils.html import escape
 | 
			
		||||
from django.utils.http import is_safe_url
 | 
			
		||||
from django.utils.safestring import mark_safe
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.decorators.csrf import requires_csrf_token
 | 
			
		||||
from django.views.defaults import ERROR_500_TEMPLATE_NAME
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
@@ -106,6 +108,7 @@ class ObjectListView(View):
 | 
			
		||||
 | 
			
		||||
        return csv_data
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request):
 | 
			
		||||
 | 
			
		||||
        model = self.queryset.model
 | 
			
		||||
@@ -713,6 +716,7 @@ class ComponentCreateView(View):
 | 
			
		||||
    model_form = None
 | 
			
		||||
    template_name = None
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        parent = get_object_or_404(self.parent_model, pk=pk)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,12 @@
 | 
			
		||||
from django.conf import settings
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.mixins import PermissionRequiredMixin
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.db.models import Count
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.views.decorators.cache import cache_page
 | 
			
		||||
from django.views.generic import View
 | 
			
		||||
 | 
			
		||||
from dcim.models import Device, Interface
 | 
			
		||||
@@ -106,6 +109,7 @@ class ClusterListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class ClusterView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'virtualization.view_cluster'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        cluster = get_object_or_404(Cluster, pk=pk)
 | 
			
		||||
@@ -168,6 +172,7 @@ class ClusterAddDevicesView(PermissionRequiredMixin, View):
 | 
			
		||||
    form = forms.ClusterAddDevicesForm
 | 
			
		||||
    template_name = 'virtualization/cluster_add_devices.html'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        cluster = get_object_or_404(Cluster, pk=pk)
 | 
			
		||||
@@ -263,6 +268,7 @@ class VirtualMachineListView(PermissionRequiredMixin, ObjectListView):
 | 
			
		||||
class VirtualMachineView(PermissionRequiredMixin, View):
 | 
			
		||||
    permission_required = 'virtualization.view_virtualmachine'
 | 
			
		||||
 | 
			
		||||
    @method_decorator(cache_page(settings.CACHE_TIMEOUT))
 | 
			
		||||
    def get(self, request, pk):
 | 
			
		||||
 | 
			
		||||
        virtualmachine = get_object_or_404(VirtualMachine.objects.select_related('tenant__group'), pk=pk)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ django-cors-headers==2.5.2
 | 
			
		||||
django-debug-toolbar==1.11
 | 
			
		||||
django-filter==2.1.0
 | 
			
		||||
django-mptt==0.9.1
 | 
			
		||||
django-redis==4.5.0
 | 
			
		||||
django-tables2==2.0.6
 | 
			
		||||
django-taggit==1.1.0
 | 
			
		||||
django-taggit-serializer==0.1.7
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user