1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

211 lines
6.2 KiB
Python
Raw Normal View History

2017-05-24 11:33:11 -04:00
from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from django.http import Http404, HttpResponse
from django.shortcuts import get_object_or_404
2017-03-08 16:12:14 -05:00
from rest_framework.decorators import detail_route
2017-09-26 17:31:16 -04:00
from rest_framework.exceptions import PermissionDenied
2017-09-21 16:32:05 -04:00
from rest_framework.response import Response
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
2016-03-01 11:23:03 -05:00
2017-03-08 16:12:14 -05:00
from extras import filters
from extras.models import CustomField, ExportTemplate, Graph, ImageAttachment, ReportResult, TopologyMap, UserAction
2017-09-25 17:27:58 -04:00
from extras.reports import get_report, get_reports
from utilities.api import FieldChoicesViewSet, IsAuthenticatedOrLoginNotRequired, ModelViewSet
2017-03-08 16:12:14 -05:00
from . import serializers
2016-03-01 11:23:03 -05:00
#
# Field choices
#
class ExtrasFieldChoicesViewSet(FieldChoicesViewSet):
fields = (
(CustomField, ['type']),
(Graph, ['type']),
)
#
# Custom fields
#
2017-01-24 17:12:16 -05:00
class CustomFieldModelViewSet(ModelViewSet):
2016-08-22 13:20:30 -04:00
"""
Include the applicable set of CustomFields in the ModelViewSet context.
2016-08-22 13:20:30 -04:00
"""
2017-01-24 17:12:16 -05:00
def get_serializer_context(self):
# Gather all custom fields for the model
content_type = ContentType.objects.get_for_model(self.queryset.model)
custom_fields = content_type.custom_fields.prefetch_related('choices')
2016-08-22 15:16:49 -04:00
# Cache all relevant CustomFieldChoices. This saves us from having to do a lookup per select field per object.
custom_field_choices = {}
2017-01-24 17:12:16 -05:00
for field in custom_fields:
2016-08-22 15:16:49 -04:00
for cfc in field.choices.all():
custom_field_choices[cfc.id] = cfc.value
2017-01-24 17:12:16 -05:00
custom_field_choices = custom_field_choices
context = super(CustomFieldModelViewSet, self).get_serializer_context()
context.update({
2017-01-24 17:12:16 -05:00
'custom_fields': custom_fields,
'custom_field_choices': custom_field_choices,
})
return context
2017-01-24 17:12:16 -05:00
def get_queryset(self):
# Prefetch custom field values
return super(CustomFieldModelViewSet, self).get_queryset().prefetch_related('custom_field_values__field')
2016-08-22 13:20:30 -04:00
#
# Graphs
#
class GraphViewSet(ModelViewSet):
2017-03-20 15:14:33 -04:00
queryset = Graph.objects.all()
serializer_class = serializers.GraphSerializer
write_serializer_class = serializers.WritableGraphSerializer
filter_class = filters.GraphFilter
#
# Export templates
#
class ExportTemplateViewSet(ModelViewSet):
queryset = ExportTemplate.objects.all()
serializer_class = serializers.ExportTemplateSerializer
filter_class = filters.ExportTemplateFilter
#
# Topology maps
#
class TopologyMapViewSet(ModelViewSet):
2017-03-08 16:12:14 -05:00
queryset = TopologyMap.objects.select_related('site')
serializer_class = serializers.TopologyMapSerializer
write_serializer_class = serializers.WritableTopologyMapSerializer
filter_class = filters.TopologyMapFilter
2017-03-08 16:12:14 -05:00
@detail_route()
def render(self, request, pk):
2017-03-08 16:12:14 -05:00
tmap = get_object_or_404(TopologyMap, pk=pk)
2017-03-08 16:30:32 -05:00
img_format = 'png'
2016-06-24 14:01:57 -04:00
try:
2017-03-08 16:30:32 -05:00
data = tmap.render(img_format=img_format)
2016-06-24 14:01:57 -04:00
except:
2017-03-08 16:12:14 -05:00
return HttpResponse(
"There was an error generating the requested graph. Ensure that the GraphViz executables have been "
"installed correctly."
)
2017-03-08 16:30:32 -05:00
response = HttpResponse(data, content_type='image/{}'.format(img_format))
response['Content-Disposition'] = 'inline; filename="{}.{}"'.format(tmap.slug, img_format)
return response
#
# Image attachments
#
class ImageAttachmentViewSet(ModelViewSet):
queryset = ImageAttachment.objects.all()
serializer_class = serializers.ImageAttachmentSerializer
write_serializer_class = serializers.WritableImageAttachmentSerializer
#
# Reports
#
2017-09-21 16:32:05 -04:00
class ReportViewSet(ViewSet):
permission_classes = [IsAuthenticatedOrLoginNotRequired]
2017-09-21 16:32:05 -04:00
_ignore_model_permissions = True
exclude_from_schema = True
2017-09-25 17:27:58 -04:00
lookup_value_regex = '[^/]+' # Allow dots
2017-09-21 16:32:05 -04:00
2017-09-26 16:36:43 -04:00
def _retrieve_report(self, pk):
# Read the PK as "<module>.<report>"
if '.' not in pk:
raise Http404
module_name, report_name = pk.split('.', 1)
2017-09-21 16:32:05 -04:00
2017-09-26 16:36:43 -04:00
# Raise a 404 on an invalid Report module/name
report = get_report(module_name, report_name)
if report is None:
raise Http404
return report
def list(self, request):
"""
Compile all reports and their related results (if any). Result data is deferred in the list view.
"""
2017-09-25 17:27:58 -04:00
report_list = []
2017-09-26 16:36:43 -04:00
# Iterate through all available Reports.
2017-09-21 16:32:05 -04:00
for module_name, reports in get_reports():
2017-09-26 16:36:43 -04:00
for report in reports:
# Attach the relevant ReportResult (if any) to each Report.
report.result = ReportResult.objects.filter(report=report.full_name).defer('data').first()
report_list.append(report)
serializer = serializers.ReportSerializer(report_list, many=True, context={
'request': request,
})
2017-09-25 17:27:58 -04:00
return Response(serializer.data)
def retrieve(self, request, pk):
2017-09-26 16:36:43 -04:00
"""
Retrieve a single Report identified as "<module>.<report>".
"""
2017-09-25 17:27:58 -04:00
2017-09-26 16:36:43 -04:00
# Retrieve the Report and ReportResult, if any.
report = self._retrieve_report(pk)
report.result = ReportResult.objects.filter(report=report.full_name).first()
2017-09-25 17:27:58 -04:00
2017-09-26 16:36:43 -04:00
serializer = serializers.ReportDetailSerializer(report)
2017-09-25 17:27:58 -04:00
return Response(serializer.data)
@detail_route(methods=['post'])
2017-09-25 17:27:58 -04:00
def run(self, request, pk):
2017-09-26 16:36:43 -04:00
"""
Run a Report and create a new ReportResult, overwriting any previous result for the Report.
"""
2017-09-25 17:27:58 -04:00
2017-09-26 17:31:16 -04:00
# Check that the user has permission to run reports.
if not request.user.has_perm('extras.add_reportresult'):
raise PermissionDenied("This user does not have permission to run reports.")
# Retrieve and run the Report. This will create a new ReportResult.
2017-09-26 16:36:43 -04:00
report = self._retrieve_report(pk)
report.run()
2017-09-21 16:32:05 -04:00
2017-09-26 16:36:43 -04:00
serializer = serializers.ReportDetailSerializer(report)
return Response(serializer.data)
2017-09-21 16:32:05 -04:00
#
# User activity
#
class RecentActivityViewSet(ReadOnlyModelViewSet):
"""
List all UserActions to provide a log of recent activity.
"""
queryset = UserAction.objects.all()
serializer_class = serializers.UserActionSerializer
filter_class = filters.UserActionFilter