views.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import graphviz
  2. from rest_framework import generics
  3. from rest_framework.decorators import detail_route
  4. from rest_framework.viewsets import ModelViewSet
  5. from django.contrib.contenttypes.models import ContentType
  6. from django.db.models import Q
  7. from django.http import Http404, HttpResponse
  8. from django.shortcuts import get_object_or_404
  9. from circuits.models import Provider
  10. from dcim.models import Site, Device, Interface, InterfaceConnection
  11. from extras import filters
  12. from extras.models import Graph, TopologyMap, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_PROVIDER, GRAPH_TYPE_SITE
  13. from utilities.api import WritableSerializerMixin
  14. from . import serializers
  15. class CustomFieldModelViewSet(ModelViewSet):
  16. """
  17. Include the applicable set of CustomField in the ModelViewSet context.
  18. """
  19. def get_serializer_context(self):
  20. # Gather all custom fields for the model
  21. content_type = ContentType.objects.get_for_model(self.queryset.model)
  22. custom_fields = content_type.custom_fields.prefetch_related('choices')
  23. # Cache all relevant CustomFieldChoices. This saves us from having to do a lookup per select field per object.
  24. custom_field_choices = {}
  25. for field in custom_fields:
  26. for cfc in field.choices.all():
  27. custom_field_choices[cfc.id] = cfc.value
  28. custom_field_choices = custom_field_choices
  29. context = super(CustomFieldModelViewSet, self).get_serializer_context()
  30. context.update({
  31. 'custom_fields': custom_fields,
  32. 'custom_field_choices': custom_field_choices,
  33. })
  34. return context
  35. def get_queryset(self):
  36. # Prefetch custom field values
  37. return super(CustomFieldModelViewSet, self).get_queryset().prefetch_related('custom_field_values__field')
  38. class GraphListView(generics.ListAPIView):
  39. """
  40. Returns a list of relevant graphs
  41. """
  42. serializer_class = serializers.GraphSerializer
  43. def get_serializer_context(self):
  44. cls = {
  45. GRAPH_TYPE_INTERFACE: Interface,
  46. GRAPH_TYPE_PROVIDER: Provider,
  47. GRAPH_TYPE_SITE: Site,
  48. }
  49. obj = get_object_or_404(cls[self.kwargs.get('type')], pk=self.kwargs['pk'])
  50. context = super(GraphListView, self).get_serializer_context()
  51. context.update({
  52. 'graphed_object': obj,
  53. })
  54. return context
  55. def get_queryset(self):
  56. graph_type = self.kwargs.get('type', None)
  57. if not graph_type:
  58. raise Http404()
  59. queryset = Graph.objects.filter(type=graph_type)
  60. return queryset
  61. class TopologyMapViewSet(WritableSerializerMixin, ModelViewSet):
  62. queryset = TopologyMap.objects.select_related('site')
  63. serializer_class = serializers.TopologyMapSerializer
  64. write_serializer_class = serializers.WritableTopologyMapSerializer
  65. filter_class = filters.TopologyMapFilter
  66. @detail_route()
  67. def render(self, request, pk):
  68. tmap = get_object_or_404(TopologyMap, pk=pk)
  69. format = 'png'
  70. try:
  71. data = tmap.render(format=format)
  72. except:
  73. return HttpResponse(
  74. "There was an error generating the requested graph. Ensure that the GraphViz executables have been "
  75. "installed correctly."
  76. )
  77. response = HttpResponse(data, content_type='image/{}'.format(format))
  78. response['Content-Disposition'] = 'inline; filename="{}.{}"'.format(tmap.slug, format)
  79. return response