views.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. from __future__ import unicode_literals
  2. from django.contrib import messages
  3. from django.contrib.auth.decorators import permission_required
  4. from django.contrib.auth.mixins import PermissionRequiredMixin
  5. from django.db import transaction
  6. from django.db.models import Count
  7. from django.shortcuts import get_object_or_404, redirect, render
  8. from django.urls import reverse
  9. from django.views.generic import View
  10. from extras.models import Graph, GRAPH_TYPE_PROVIDER
  11. from utilities.forms import ConfirmationForm
  12. from utilities.views import (
  13. BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
  14. )
  15. from . import filters, forms, tables
  16. from .models import Circuit, CircuitTermination, CircuitType, Provider, TERM_SIDE_A, TERM_SIDE_Z
  17. #
  18. # Providers
  19. #
  20. class ProviderListView(ObjectListView):
  21. queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
  22. filter = filters.ProviderFilter
  23. filter_form = forms.ProviderFilterForm
  24. table = tables.ProviderTable
  25. template_name = 'circuits/provider_list.html'
  26. class ProviderView(View):
  27. def get(self, request, slug):
  28. provider = get_object_or_404(Provider, slug=slug)
  29. circuits = Circuit.objects.filter(provider=provider).select_related(
  30. 'type', 'tenant'
  31. ).prefetch_related(
  32. 'terminations__site'
  33. )
  34. show_graphs = Graph.objects.filter(type=GRAPH_TYPE_PROVIDER).exists()
  35. return render(request, 'circuits/provider.html', {
  36. 'provider': provider,
  37. 'circuits': circuits,
  38. 'show_graphs': show_graphs,
  39. })
  40. class ProviderEditView(PermissionRequiredMixin, ObjectEditView):
  41. permission_required = 'circuits.change_provider'
  42. model = Provider
  43. form_class = forms.ProviderForm
  44. template_name = 'circuits/provider_edit.html'
  45. default_return_url = 'circuits:provider_list'
  46. class ProviderDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  47. permission_required = 'circuits.delete_provider'
  48. model = Provider
  49. default_return_url = 'circuits:provider_list'
  50. class ProviderBulkImportView(PermissionRequiredMixin, BulkImportView):
  51. permission_required = 'circuits.add_provider'
  52. model_form = forms.ProviderCSVForm
  53. table = tables.ProviderTable
  54. default_return_url = 'circuits:provider_list'
  55. class ProviderBulkEditView(PermissionRequiredMixin, BulkEditView):
  56. permission_required = 'circuits.change_provider'
  57. cls = Provider
  58. filter = filters.ProviderFilter
  59. form = forms.ProviderBulkEditForm
  60. template_name = 'circuits/provider_bulk_edit.html'
  61. default_return_url = 'circuits:provider_list'
  62. class ProviderBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  63. permission_required = 'circuits.delete_provider'
  64. cls = Provider
  65. filter = filters.ProviderFilter
  66. default_return_url = 'circuits:provider_list'
  67. #
  68. # Circuit Types
  69. #
  70. class CircuitTypeListView(ObjectListView):
  71. queryset = CircuitType.objects.annotate(circuit_count=Count('circuits'))
  72. table = tables.CircuitTypeTable
  73. template_name = 'circuits/circuittype_list.html'
  74. class CircuitTypeEditView(PermissionRequiredMixin, ObjectEditView):
  75. permission_required = 'circuits.change_circuittype'
  76. model = CircuitType
  77. form_class = forms.CircuitTypeForm
  78. def get_return_url(self, request, obj):
  79. return reverse('circuits:circuittype_list')
  80. class CircuitTypeBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  81. permission_required = 'circuits.delete_circuittype'
  82. cls = CircuitType
  83. default_return_url = 'circuits:circuittype_list'
  84. #
  85. # Circuits
  86. #
  87. class CircuitListView(ObjectListView):
  88. queryset = Circuit.objects.select_related('provider', 'type', 'tenant').prefetch_related('terminations__site')
  89. filter = filters.CircuitFilter
  90. filter_form = forms.CircuitFilterForm
  91. table = tables.CircuitTable
  92. template_name = 'circuits/circuit_list.html'
  93. class CircuitView(View):
  94. def get(self, request, pk):
  95. circuit = get_object_or_404(Circuit.objects.select_related('provider', 'type', 'tenant__group'), pk=pk)
  96. termination_a = CircuitTermination.objects.select_related(
  97. 'site__region', 'interface__device'
  98. ).filter(
  99. circuit=circuit, term_side=TERM_SIDE_A
  100. ).first()
  101. termination_z = CircuitTermination.objects.select_related(
  102. 'site__region', 'interface__device'
  103. ).filter(
  104. circuit=circuit, term_side=TERM_SIDE_Z
  105. ).first()
  106. return render(request, 'circuits/circuit.html', {
  107. 'circuit': circuit,
  108. 'termination_a': termination_a,
  109. 'termination_z': termination_z,
  110. })
  111. class CircuitEditView(PermissionRequiredMixin, ObjectEditView):
  112. permission_required = 'circuits.change_circuit'
  113. model = Circuit
  114. form_class = forms.CircuitForm
  115. template_name = 'circuits/circuit_edit.html'
  116. default_return_url = 'circuits:circuit_list'
  117. class CircuitDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  118. permission_required = 'circuits.delete_circuit'
  119. model = Circuit
  120. default_return_url = 'circuits:circuit_list'
  121. class CircuitBulkImportView(PermissionRequiredMixin, BulkImportView):
  122. permission_required = 'circuits.add_circuit'
  123. model_form = forms.CircuitCSVForm
  124. table = tables.CircuitTable
  125. default_return_url = 'circuits:circuit_list'
  126. class CircuitBulkEditView(PermissionRequiredMixin, BulkEditView):
  127. permission_required = 'circuits.change_circuit'
  128. cls = Circuit
  129. filter = filters.CircuitFilter
  130. form = forms.CircuitBulkEditForm
  131. template_name = 'circuits/circuit_bulk_edit.html'
  132. default_return_url = 'circuits:circuit_list'
  133. class CircuitBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
  134. permission_required = 'circuits.delete_circuit'
  135. cls = Circuit
  136. filter = filters.CircuitFilter
  137. default_return_url = 'circuits:circuit_list'
  138. @permission_required('circuits.change_circuittermination')
  139. def circuit_terminations_swap(request, pk):
  140. circuit = get_object_or_404(Circuit, pk=pk)
  141. termination_a = CircuitTermination.objects.filter(circuit=circuit, term_side=TERM_SIDE_A).first()
  142. termination_z = CircuitTermination.objects.filter(circuit=circuit, term_side=TERM_SIDE_Z).first()
  143. if not termination_a and not termination_z:
  144. messages.error(request, "No terminations have been defined for circuit {}.".format(circuit))
  145. return redirect('circuits:circuit', pk=circuit.pk)
  146. if request.method == 'POST':
  147. form = ConfirmationForm(request.POST)
  148. if form.is_valid():
  149. if termination_a and termination_z:
  150. # Use a placeholder to avoid an IntegrityError on the (circuit, term_side) unique constraint
  151. with transaction.atomic():
  152. termination_a.term_side = '_'
  153. termination_a.save()
  154. termination_z.term_side = 'A'
  155. termination_z.save()
  156. termination_a.term_side = 'Z'
  157. termination_a.save()
  158. elif termination_a:
  159. termination_a.term_side = 'Z'
  160. termination_a.save()
  161. else:
  162. termination_z.term_side = 'A'
  163. termination_z.save()
  164. messages.success(request, "Swapped terminations for circuit {}.".format(circuit))
  165. return redirect('circuits:circuit', pk=circuit.pk)
  166. else:
  167. form = ConfirmationForm()
  168. return render(request, 'circuits/circuit_terminations_swap.html', {
  169. 'circuit': circuit,
  170. 'termination_a': termination_a,
  171. 'termination_z': termination_z,
  172. 'form': form,
  173. 'panel_class': 'default',
  174. 'button_class': 'primary',
  175. 'return_url': circuit.get_absolute_url(),
  176. })
  177. #
  178. # Circuit terminations
  179. #
  180. class CircuitTerminationEditView(PermissionRequiredMixin, ObjectEditView):
  181. permission_required = 'circuits.change_circuittermination'
  182. model = CircuitTermination
  183. form_class = forms.CircuitTerminationForm
  184. template_name = 'circuits/circuittermination_edit.html'
  185. def alter_obj(self, obj, request, url_args, url_kwargs):
  186. if 'circuit' in url_kwargs:
  187. obj.circuit = get_object_or_404(Circuit, pk=url_kwargs['circuit'])
  188. return obj
  189. def get_return_url(self, request, obj):
  190. return obj.circuit.get_absolute_url()
  191. class CircuitTerminationDeleteView(PermissionRequiredMixin, ObjectDeleteView):
  192. permission_required = 'circuits.delete_circuittermination'
  193. model = CircuitTermination