admin.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. from django.contrib import admin
  2. from django.contrib.gis import admin as geo_admin
  3. from django.db import models
  4. from django.db.models import Q
  5. from django.forms import ModelForm, BaseInlineFormSet
  6. from django.utils import timezone
  7. from django.core.urlresolvers import reverse
  8. from django.utils.html import format_html
  9. from django.core.mail import mail_managers
  10. from adhesions.models import Adhesion
  11. from .models import Service, ServiceType, IPResource, Route, ServiceAllocation, Antenna, AntennaAllocation, Allocation
  12. from .utils import notify_allocation
  13. ### Filters
  14. class ResourceInUseFilter(admin.SimpleListFilter):
  15. title = 'disponibilité'
  16. parameter_name = 'available'
  17. def lookups(self, request, model_admin):
  18. return (
  19. (1, 'Disponible'),
  20. (0, 'Non disponible'),
  21. )
  22. def queryset(self, request, queryset):
  23. available_filter = Q(reserved=False, in_use=False)
  24. if self.value() == '0': # non disponible
  25. return queryset.exclude(available_filter)
  26. if self.value() == '1': # disponible
  27. return queryset.filter(available_filter)
  28. ### Inlines
  29. class AllocationInlineFormSet(BaseInlineFormSet):
  30. def save_new(self, form, commit=True):
  31. obj = super().save_new(form, commit)
  32. if type(obj) == ServiceAllocation:
  33. notify_allocation(self.request, obj)
  34. return obj
  35. def save_existing(self, form, instance, commit=True):
  36. old = type(instance).objects.get(pk=instance.pk)
  37. if type(instance) == ServiceAllocation:
  38. notify_allocation(self.request, instance, old)
  39. return super().save_existing(form, instance, commit)
  40. class AllocationInline(admin.TabularInline):
  41. formset = AllocationInlineFormSet
  42. extra = 0
  43. verbose_name_plural = 'Allocations'
  44. show_change_link = True
  45. def get_formset(self, request, obj=None, **kwargs):
  46. formset = super().get_formset(request, obj, **kwargs)
  47. formset.request = request
  48. return formset
  49. def get_max_num(self, request, obj=None, **kwargs):
  50. existing = obj.allocations.count() if obj else 0
  51. # pour simplifier la validation, on ajoute qu’une allocation à la fois
  52. # il faudrait surcharger la méthode clean du formset pour supprimer cette limite
  53. return existing + 1
  54. def has_delete_permission(self, request, obj=None):
  55. return False
  56. class ServiceAllocationInline(AllocationInline):
  57. model = ServiceAllocation
  58. fields = ('id', 'service', 'resource', 'route', 'start', 'end')
  59. raw_id_fields = ('service', 'resource',)
  60. class AntennaAllocationInline(AllocationInline):
  61. model = AntennaAllocation
  62. fields = ('id', 'antenna', 'resource', 'start', 'end')
  63. raw_id_fields = ('antenna', 'resource',)
  64. ### Actions
  65. def ends_resource(resource, request, queryset):
  66. now = timezone.now()
  67. queryset.exclude(start__lte=now, end__isnull=False).update(end=now)
  68. # TODO: send mail
  69. ends_resource.short_description = 'Terminer les allocations sélectionnées'
  70. ### ModelAdmin
  71. class ServiceAdmin(admin.ModelAdmin):
  72. list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active')
  73. list_select_related = ('adhesion',) # to reduce database requests
  74. list_filter = (
  75. 'active',
  76. ('service_type', admin.RelatedOnlyFieldListFilter),
  77. )
  78. inlines = (ServiceAllocationInline,)
  79. search_fields = ('id', 'service_type__name', 'label', 'adhesion__id',)
  80. raw_id_fields = ('adhesion',)
  81. get_adhesion_link = lambda self, service: service.adhesion.get_adhesion_link()
  82. get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
  83. get_adherent_link = lambda self, service: service.adhesion.get_adherent_link()
  84. get_adherent_link.short_description = Adhesion.get_adherent_link.short_description
  85. def get_actions(self, request):
  86. actions = super().get_actions(request)
  87. if 'delete_selected' in actions:
  88. del actions['delete_selected']
  89. return actions
  90. def has_delete_permission(self, request, obj=None):
  91. return False
  92. class IPResourceAdmin(admin.ModelAdmin):
  93. list_display = ('__str__', 'available_display', 'last_use',)
  94. list_filter = (
  95. 'category',
  96. ResourceInUseFilter,
  97. ('prefixes', admin.RelatedOnlyFieldListFilter),
  98. )
  99. fields = ('ip', 'reserved', 'notes')
  100. readonly_fields = ('ip', 'reserved',)
  101. search_fields = ('ip',)
  102. def get_inline_instances(self, request, obj=None):
  103. if obj:
  104. if obj.category == 0:
  105. inlines = (ServiceAllocationInline,)
  106. elif obj.category == 1:
  107. inlines = (AntennaAllocationInline,)
  108. else:
  109. inlines = ()
  110. return [inline(self.model, self.admin_site) for inline in inlines]
  111. def get_queryset(self, request):
  112. qs = super().get_queryset(request)
  113. qs = qs.annotate(last_use=models.Case(
  114. models.When(category=0, then=models.Max('service_allocation__end')),
  115. models.When(category=1, then=models.Max('antenna_allocation__end')),
  116. ))
  117. return qs
  118. def available_display(self, obj):
  119. return not obj.reserved and not obj.in_use
  120. available_display.short_description = 'Disponible'
  121. available_display.boolean = True
  122. def last_use(self, obj):
  123. if obj.allocations.exists():
  124. return obj.allocations.last().end
  125. else:
  126. return None
  127. last_use.short_description = 'Dernière utilisation'
  128. last_use.admin_order_field = 'last_use'
  129. def get_actions(self, request):
  130. actions = super().get_actions(request)
  131. if 'delete_selected' in actions:
  132. del actions['delete_selected']
  133. return actions
  134. def has_add_permission(self, request, obj=None):
  135. return False
  136. def has_delete_permission(self, request, obj=None):
  137. return False
  138. class RouteAdmin(admin.ModelAdmin):
  139. fields = ('name',)
  140. readonly_fields = ('name',)
  141. def has_add_permission(self, request, obj=None):
  142. return False
  143. def get_actions(self, request):
  144. actions = super().get_actions(request)
  145. if 'delete_selected' in actions:
  146. del actions['delete_selected']
  147. return actions
  148. def has_delete_permission(self, request, obj=None):
  149. return False
  150. class ServiceTypeAdmin(admin.ModelAdmin):
  151. fields = ('name',)
  152. readonly_fields = ('name',)
  153. def get_actions(self, request):
  154. actions = super().get_actions(request)
  155. if 'delete_selected' in actions:
  156. del actions['delete_selected']
  157. return actions
  158. def has_add_permission(self, request, obj=None):
  159. return False
  160. def has_delete_permission(self, request, obj=None):
  161. return False
  162. class AntennaAdmin(geo_admin.OSMGeoAdmin):
  163. inlines = (AntennaAllocationInline,)
  164. admin.site.register(ServiceType, ServiceTypeAdmin)
  165. admin.site.register(Service, ServiceAdmin)
  166. admin.site.register(IPResource, IPResourceAdmin)
  167. admin.site.register(Route, RouteAdmin)
  168. geo_admin.site.register(Antenna, AntennaAdmin)