views.py 9.5 KB

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