admin.py 7.0 KB

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