Browse Source

amélioration gestion des adhésions

Élie Bouttier 7 years ago
parent
commit
7807a56f19

+ 1 - 15
accounts/models.py

@@ -1,5 +1,4 @@
 from django.db import models
-from django.contrib.contenttypes.models import ContentType
 from django.urls import reverse
 
 
@@ -18,21 +17,8 @@ class Profile(models.Model):
         verbose_name = 'profil'
 
     @property
-    def adhesion(self): # user adhesion
-        ctype = ContentType.objects.get_for_model(User)
-        try:
-            return Adhesion.objects.get(adherent_type=ctype, adherent_id=self.user.pk)
-        except Adhesion.DoesNotExist:
-            return None
-
-    @property
     def adhesions(self): # user and corporations (for which the user is a member) adhesions
-        user_type = ContentType.objects.get_for_model(User)
-        corp_type = ContentType.objects.get_for_model(Corporation)
-        return Adhesion.objects.filter(
-            models.Q(adherent_type=user_type, adherent_id=self.user.pk)
-            | models.Q(adherent_type=corp_type, adherent_id__in=Corporation.objects.filter(members=self.user).values_list('pk'))
-        )
+        return Adhesion.objects.filter(models.Q(user__pk=self.user.pk) | models.Q(corporation__members__profile__pk=self.pk))
 
     def __str__(self):
         return self.user.get_full_name() or self.user.username

+ 113 - 118
adhesions/admin.py

@@ -6,29 +6,28 @@ from django.contrib.auth.models import User as AuthUser, Group
 from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
 from django.http import HttpResponseRedirect
 
-from .forms import AdhesionForm, UserCreationForm
+from .forms import UserCreationForm
 from .models import User, Corporation, Adhesion
 from accounts.models import Profile
 from services.models import Service
 from banking.admin import PaymentInline
 
 
-class AdhesionInline(GenericTabularInline):
-    model = Adhesion
-    ct_field = 'adherent_type'
-    ct_fk_field = 'adherent_id'
-    form = AdhesionForm
-    min_num = 1
-    max_num = 1
-    extra = 0
-    show_change_link = True
+### Inlines
+
+class ProfileInline(admin.StackedInline):
+    model = Profile
+
+    def has_add_permission(self, request):
+        return False
 
     def has_delete_permission(self, request, obj=None):
         return False
 
 
-class ProfileInline(admin.StackedInline):
-    model = Profile
+class AdhesionInline(admin.StackedInline):
+    model = Adhesion
+    fields = ('id', 'active', 'notes',)
 
     def has_add_permission(self, request):
         return False
@@ -51,50 +50,79 @@ class ServiceInline(admin.StackedInline):
         return False
 
 
-class UserIsAdherentFilter(admin.SimpleListFilter):
-    title = 'status adhérent'
-    parameter_name = 'adherent'
+### Filters
+
+class AdherentTypeFilter(admin.SimpleListFilter):
+    title = 'type d’adhérent'
+    parameter_name = 'type'
 
     def lookups(self, request, model_admin):
         return (
-            ('1', 'Oui'),
-            ('0', 'Non'),
+            ('physique', 'Personne physique'),
+            ('morale', 'Personne morale'),
         )
 
     def queryset(self, request, queryset):
-        adhesion_list = Adhesion.objects.values_list('adherent_id')
-        if self.value() == '0':
-            return queryset.exclude(pk__in=adhesion_list)
-        if self.value() == '1':
-            return queryset.filter(pk__in=adhesion_list)
+        if self.value() == 'physique':
+            return queryset.filter(user__isnull=False)
+        if self.value() == 'morale':
+            return queryset.filter(corporation__isnull=False)
+
+
+### Mixins
+
+class AdtSearchMixin:
+    adhesion_search_field = 'id'
+
+    def get_search_results(self, request, queryset, search_term):
+        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
+        if search_term[:3] == 'ADT':
+            try:
+                adh_id = int(search_term[3:])
+            except ValueError:
+                pass
+            else:
+                queryset |= self.model.objects.filter(**{self.adhesion_search_field: adh_id})
+        return queryset, use_distinct
+
 
+### ModelAdmin
 
-class UserAdmin(AuthUserAdmin):
+class UserAdmin(AdtSearchMixin, AuthUserAdmin):
     list_display = AuthUserAdmin.list_display + ('get_adhesion_link',)
-    list_filter = AuthUserAdmin.list_filter + (UserIsAdherentFilter,)
+    list_select_related = ('profile', 'adhesion',)
+    ordering = ('adhesion__id',)
+    search_fields = AuthUserAdmin.search_fields + ('=adhesion__id', 'adhesion__notes',)
     readonly_fields = ('get_adhesion_link',)
+    adhesion_search_field = 'adhesion__id'
 
-    def get_adhesion_link(self, user):
-        adhesion = user.adhesion
-        if adhesion:
-            return adhesion.get_adhesion_link()
-    get_adhesion_link.short_description = 'Numéro d’adhérent'
+    def get_adhesion_id(self, user):
+        return user.adhesion
+    get_adhesion_id.short_description = 'Numéro d’adhérent'
+    get_adhesion_id.admin_order_field = 'adhesion__id'
+
+    get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
+    get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
+
+    def get_inline_instances(self, request, obj=None):
+        if obj:
+            inlines = (ProfileInline, AdhesionInline,)
+        else:
+            inlines = ()
+        return [inline(self.model, self.admin_site) for inline in inlines]
 
     def get_form(self, request, obj=None, **kwargs):
         if obj:
-            if obj.profile.adhesion:
-                UserAdmin.inlines = (ProfileInline,)
-            else:
-                UserAdmin.inlines = (ProfileInline, AdhesionInline,)
             return super().get_form(request, obj, **kwargs)
         else:
-            UserAdmin.inlines = (AdhesionInline,)
             return UserCreationForm
 
     def get_fieldsets(self, request, obj=None):
         if obj:
             fieldsets = (
-                AuthUserAdmin.fieldsets[1],
+                (AuthUserAdmin.fieldsets[1][0], {
+                    'fields': ('get_adhesion_link',) + AuthUserAdmin.fieldsets[1][1]['fields'],
+                }),
                 ('Nom d’utilisateur et mot de passe', {
                     'classes': ('collapse',),
                     'fields': AuthUserAdmin.fieldsets[0][1]['fields'],
@@ -108,16 +136,10 @@ class UserAdmin(AuthUserAdmin):
                     'fields': AuthUserAdmin.fieldsets[3][1]['fields'],
                 }),
             )
-            if obj.profile.adhesion:
-                fieldsets = (
-                    (None, {
-                        'fields': ('get_adhesion_link',),
-                    }),
-                ) + fieldsets
         else:
             fieldsets = (
                 (None, {
-                    'fields': ('first_name', 'last_name', 'username',),
+                    'fields': ('first_name', 'last_name', 'username', 'email',),
                 }),
             )
         return fieldsets
@@ -132,52 +154,29 @@ class UserAdmin(AuthUserAdmin):
         return obj and not obj.adhesion
 
 
-class AdherentTypeFilter(admin.SimpleListFilter):
-    title = 'type d’adhérent'
-    parameter_name = 'type'
-
-    def lookups(self, request, model_admin):
-        return (
-            ('physique', 'Personne physique'),
-            ('morale', 'Personne morale'),
-        )
-
-    def queryset(self, request, queryset):
-        if self.value() == 'physique':
-            return queryset.filter(adherent_type__app_label='auth',
-                                   adherent_type__model='user')
-        if self.value() == 'morale':
-            return queryset.filter(adherent_type__app_label='adhesions',
-                                   adherent_type__model='corporation')
-
+class CorporationAdmin(AdtSearchMixin, admin.ModelAdmin):
+    list_display = ('social_reason', 'get_adhesion_link',)
+    list_select_related = ('adhesion',)
+    ordering = ('adhesion__id',)
+    search_fields = ('social_reason', 'description', 'email', 'phone_number', 'address', 'notes', 'adhesion__id', 'adhesion__notes',)
+    readonly_fields = ('get_adhesion_link',)
+    filter_horizontal = ('members',)
+    adhesion_search_field = 'adhesion__id'
 
-class AdhesionAdmin(admin.ModelAdmin):
-    list_display = ('get_id', 'type', 'get_adherent_link', 'active')
-    list_filter = (AdherentTypeFilter, 'active',)
-    fields = ('id', 'type', 'get_adherent_link', 'active', 'notes')
-    readonly_fields = ('id', 'type', 'get_adherent_link',)
-    search_fields = ('=id', 'notes',)
-    inlines = (ServiceInline,)#PaymentInline,)
+    def get_adhesion_id(self, corp):
+        return corp.adhesion
+    get_adhesion_id.short_description = 'Numéro d’adhérent'
+    get_adhesion_id.admin_order_field = 'adhesion__id'
 
-    def get_id(self, obj):
-        return 'ADT%d' % obj.id
-    get_id.short_description = 'Numéro d’adhérent'
+    get_adhesion_link = lambda self, corporation: corporation.adhesion.get_adhesion_link()
+    get_adhesion_link.short_description = Adhesion.get_adhesion_link.short_description
 
-    def get_search_results(self, request, queryset, search_term):
-        queryset, use_distinct = super().get_search_results(request, queryset, search_term)
-        users = User.objects.filter(
-                    Q(username__icontains=search_term)
-                    | Q(first_name__icontains=search_term)
-                    | Q(last_name__icontains=search_term)
-        )
-        user_type = ContentType.objects.get_for_model(User)
-        queryset |= Adhesion.objects.filter(adherent_type=user_type,
-                                            adherent_id__in=users.values_list('pk'))
-        corporations = Corporation.objects.filter(social_reason__icontains=search_term)
-        corporation_type = ContentType.objects.get_for_model(Corporation)
-        queryset |= Adhesion.objects.filter(adherent_type=corporation_type,
-                                            adherent_id__in=corporations.values_list('pk'))
-        return queryset, use_distinct
+    def get_inline_instances(self, request, obj=None):
+        if obj:
+            inlines = (AdhesionInline,)
+        else:
+            inlines = ()
+        return [inline(self.model, self.admin_site) for inline in inlines]
 
     def get_actions(self, request):
         actions = super().get_actions(request)
@@ -185,23 +184,38 @@ class AdhesionAdmin(admin.ModelAdmin):
             del actions['delete_selected']
         return actions
 
-    def has_add_permission(self, request):
-        return False
+    def get_fieldsets(self, request, obj=None):
+        fieldsets = super().get_fieldsets(request, obj)
+        # put adhesion id on top
+        if obj:
+            fields = fieldsets[0][1]['fields']
+            fields.remove('get_adhesion_link')
+            fieldsets = (
+                (None, {
+                    'fields': ['get_adhesion_link'] + fields,
+                }),
+            )
+        return fieldsets
 
     def has_delete_permission(self, request, obj=None):
         return False
 
 
-class CorporationAdmin(admin.ModelAdmin):
-    list_display = ('social_reason', 'get_adhesion_link')
-    search_fields = ('social_reason',)
-    filter_horizontal = ('members',)
+class AdhesionAdmin(AdtSearchMixin, admin.ModelAdmin):
+    list_display = ('get_id', 'type', 'get_adherent_link',)
+    list_filter = (AdherentTypeFilter, 'active',)
+    list_select_related = ('user', 'user__profile', 'corporation',)
+    fields = ('id', 'type', 'get_adherent_link',)
+    readonly_fields = ('id', 'type', 'get_adherent_link',)
+    search_fields = ('=id', 'notes',) \
+                    + tuple(['user__%s' % f for f in UserAdmin.search_fields if '__' not in f]) \
+                    + tuple(['corporation__%s' % f for f in CorporationAdmin.search_fields if '__' not in f])
+    inlines = (ServiceInline,)#PaymentInline,)
 
-    def get_adhesion_link(self, corp):
-        adhesion = corp.adhesion
-        if adhesion:
-            return adhesion.get_adhesion_link()
-    get_adhesion_link.short_description = 'Numéro d’adhérent'
+    def get_id(self, obj):
+        return 'ADT%d' % obj.id
+    get_id.short_description = 'Numéro d’adhérent'
+    get_id.admin_order_field = 'id'
 
     def get_actions(self, request):
         actions = super().get_actions(request)
@@ -209,30 +223,11 @@ class CorporationAdmin(admin.ModelAdmin):
             del actions['delete_selected']
         return actions
 
-    def get_readonly_fields(self, request, obj=None):
-        readonly_fields = super().get_readonly_fields(request, obj)
-        if obj and obj.adhesion:
-            readonly_fields += ('get_adhesion_link',)
-        return readonly_fields
-
-    def get_fieldsets(self, request, obj=None):
-        fieldsets = super().get_fieldsets(request, obj)
-        # put adhesion_link on top
-        if obj and obj.adhesion:
-            CorporationAdmin.inlines = ()
-            fields = fieldsets[0][1]['fields']
-            fields.remove('get_adhesion_link')
-            fieldsets = (
-                (None, {
-                    'fields': ['get_adhesion_link'] + fields,
-                }),
-            )
-        else:
-            CorporationAdmin.inlines = (AdhesionInline,)
-        return fieldsets
+    def has_add_permission(self, request):
+        return False
 
     def has_delete_permission(self, request, obj=None):
-        return obj and not obj.adhesion
+        return False
 
 
 admin.site.unregister(AuthUser)

+ 3 - 0
adhesions/apps.py

@@ -4,3 +4,6 @@ from django.apps import AppConfig
 class AdhesionsConfig(AppConfig):
     name = 'adhesions'
     verbose_name = 'Adhérents'
+
+    def ready(self):
+        import adhesions.signals  # noqa

+ 1 - 15
adhesions/forms.py

@@ -9,24 +9,10 @@ class UserCreationForm(forms.ModelForm):
 
     class Meta:
         model = User
-        fields = ('first_name', 'last_name', 'username',)
+        fields = ('first_name', 'last_name', 'username', 'email')
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self.fields['first_name'].required = True
         self.fields['last_name'].required = True
         self.fields['username'].required = False
-
-
-class AdhesionForm(forms.ModelForm):
-    adhesion = forms.BooleanField(label='Adhérent ?', required=False)
-
-    class Meta:
-        model = Adhesion
-        exclude = ()
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        if self.instance.id:
-            self.fields['adhesion'].initial = True
-            self.fields['adhesion'].widget.attrs['readonly'] = True

+ 45 - 0
adhesions/migrations/0014_auto_20170614_2242.py

@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.2 on 2017-06-14 20:42
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+def migrate_adhesions(apps, schema_editor):
+    User = apps.get_model("adhesions", "User")
+    Corporation = apps.get_model("adhesions", "Corporation")
+    Adhesion = apps.get_model("adhesions", "Adhesion")
+    ContentType = apps.get_model("contenttypes", "ContentType")
+    user_type = ContentType.objects.get_for_model(User)
+    corp_type = ContentType.objects.get_for_model(Corporation)
+    db_alias = schema_editor.connection.alias
+    for adh in Adhesion.objects.using(db_alias).all():
+        if adh.adherent_type == user_type:
+            adh.user = User.objects.using(db_alias).get(pk=adh.adherent_id)
+        else:
+            assert(adh.adherent_type == corp_type)
+            adh.corporation = Corporation.objects.using(db_alias).get(pk=adh.adherent_id)
+        adh.save()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('adhesions', '0013_adhesion_active'),
+        ('accounts', '0006_auto_20170607_2306'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='adhesion',
+            name='user',
+            field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='adhesions.User'),
+        ),
+        migrations.AddField(
+            model_name='adhesion',
+            name='corporation',
+            field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='adhesions.Corporation'),
+        ),
+        migrations.RunPython(migrate_adhesions),
+    ]

+ 44 - 0
adhesions/migrations/0015_auto_20170614_2312.py

@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.2 on 2017-06-14 21:12
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def create_missing_adhesions(apps, schema_editor):
+    User = apps.get_model("adhesions", "User")
+    Corporation = apps.get_model("adhesions", "Corporation")
+    Adhesion = apps.get_model("adhesions", "Adhesion")
+    ContentType = apps.get_model("contenttypes", "ContentType")
+    user_type = ContentType.objects.get_for_model(User)
+    corp_type = ContentType.objects.get_for_model(Corporation)
+    db_alias = schema_editor.connection.alias
+    for user in User.objects.using(db_alias).filter(adhesion__isnull=True).all():
+        if not Adhesion.objects.using(db_alias).filter(user__pk=user.pk).exists():
+            Adhesion.objects.using(db_alias).create(user=user)
+    for corp in Corporation.objects.using(db_alias).filter(adhesion__isnull=True).all():
+        if not Adhesion.objects.using(db_alias).filter(corporation__pk=corp.pk).exists():
+            Adhesion.objects.using(db_alias).create(corporation=corp)
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('adhesions', '0014_auto_20170614_2242'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='adhesion',
+            unique_together=set([]),
+        ),
+        migrations.RemoveField(
+            model_name='adhesion',
+            name='adherent_id',
+        ),
+        migrations.RemoveField(
+            model_name='adhesion',
+            name='adherent_type',
+        ),
+        migrations.RunPython(create_missing_adhesions),
+    ]

+ 57 - 64
adhesions/models.py

@@ -10,16 +10,54 @@ from djadhere.utils import get_active_filter
 from banking.models import Payment
 
 
+class User(AuthUser):
+    def get_model_perms(self, request):
+        return {}
+
+    @property
+    def adhesions(self): # user and corporations (for which the user is a member) adhesions
+        return self.profile.adhesions
+
+    class Meta:
+        proxy = True
+        verbose_name = 'personne physique'
+        verbose_name_plural = 'personnes physiques'
+
+    def get_absolute_url(self):
+        return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
+
+    def __str__(self):
+        return self.get_full_name() or self.username
+
+
+class Corporation(models.Model):
+    social_reason = models.CharField(max_length=256, verbose_name='Raison sociale', unique=True)
+    description = models.TextField(blank=True, default='')
+    members = models.ManyToManyField(User, blank=True, verbose_name='Membres',
+                                     related_name='corporations', related_query_name='corporation')
+    email = models.EmailField(verbose_name='Adresse e-mail', blank=True)
+    phone_number = models.CharField(max_length=16, blank=True, default='',
+                                    verbose_name='Numéro de téléphone')
+    address = models.TextField(blank=True, default='', verbose_name='Adresse')
+    notes = models.TextField(blank=True, default='')
+
+    class Meta:
+        verbose_name = 'personne morale'
+        verbose_name_plural = 'personnes morales'
+
+    def get_absolute_url(self):
+        return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
+
+    def __str__(self):
+        return self.social_reason
+
+
 # Terminologie : une « adhésion » désgine une instance de ce modèle
 # tandis qu’un « adhérent » désigne un user ou une corporation.
 class Adhesion(models.Model):
     limit = models.Q(app_label='auth', model='user') \
           | models.Q(app_label='adhesions', model='corporation')
     id = models.AutoField(verbose_name='Numéro d’adhérent', primary_key=True, editable=True)
-    adherent_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
-                                      limit_choices_to=limit, verbose_name='Type d’adhérent')
-    adherent_id = models.PositiveIntegerField(verbose_name='ID')
-    adherent = GenericForeignKey('adherent_type', 'adherent_id')
     contributions = GenericRelation(Payment,
                                    content_type_field='reason_type',
                                    object_id_field='reason_id',
@@ -28,9 +66,11 @@ class Adhesion(models.Model):
     notes = models.TextField(blank=True, default='')
     active = models.NullBooleanField(default=None, verbose_name='Adhésion en cours')
 
+    user = models.OneToOneField(User, null=True)
+    corporation = models.OneToOneField(Corporation, null=True)
+
     class Meta:
         verbose_name = 'adhésion'
-        unique_together = ("adherent_type", "adherent_id")
         ordering = ('id',)
 
     @property
@@ -43,10 +83,10 @@ class Adhesion(models.Model):
         # empêcher cette possibilité, si cette exception est levé on veut recevoir un mail avec l’erreur !
 
     def is_physical(self):
-        return self.adherent_type.app_label == 'auth' and self.adherent_type.model == 'user'
+        return self.user is not None
 
     def is_moral(self):
-        return self.adherent_type.app_label == 'adhesions' and self.adherent_type.model == 'corporation'
+        return self.corporation is not None
 
     @property
     def type(self):
@@ -55,74 +95,27 @@ class Adhesion(models.Model):
         else:
             return 'Personne morale'
 
-    def get_adherent_name(self):
+    @property
+    def adherent(self):
         if self.is_physical():
-            return str(self.adherent.profile)
+            return self.user
         else:
-            return str(self.adherent)
-    get_adherent_name.short_description = 'Nom ou raison sociale'
+            return self.corporation
 
     def get_adherent_link(self):
-        url = reverse('admin:adhesions_%s_change' % self.adherent._meta.model_name, args=(self.adherent.id,))
-        return format_html(u'<a href="{}">{}</a>', url, self.get_adherent_name())
+        return format_html(u'<a href="{}">{}</a>', self.adherent.get_absolute_url(), self.adherent)
     get_adherent_link.short_description = 'Nom ou raison sociale'
 
     def get_adhesion_link(self):
-        url = reverse('admin:adhesions_adhesion_change', args=(self.id,))
-        return format_html(u'<a href="{}">ADT{}</a>', url, str(self.id))
+        return format_html(u'<a href="{}">ADT{}</a>', self.get_absolute_url(), str(self.id))
     get_adhesion_link.short_description = 'Numéro d’adhérent'
 
+    def get_absolute_url(self):
+        return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=(self.pk,))
+
     def __str__(self):
         return 'ADT%d' % self.id
         if self.id is None:
             return '?'
         else:
-            return 'ADT%d (%s)' % (self.id, self.get_adherent_name())
-
-
-class User(AuthUser):
-    class Meta:
-        proxy = True
-        verbose_name = 'personne physique'
-        verbose_name_plural = 'personnes physiques'
-
-    def get_model_perms(self, request):
-        return {}
-
-    @property
-    def adhesion(self): # user adhesion
-        return self.profile.adhesion
-
-    @property
-    def adhesions(self): # user and corporations (for which the user is a member) adhesions
-        return self.profile.adhesions
-    
-    def __str__(self):
-        return self.get_full_name() or self.username
-
-
-class Corporation(models.Model):
-    social_reason = models.CharField(max_length=256, verbose_name='Raison sociale', unique=True)
-    description = models.TextField(blank=True, default='')
-    members = models.ManyToManyField(User, blank=True, verbose_name='Membres',
-                                     related_name='corporations', related_query_name='corporation')
-    email = models.EmailField(verbose_name='Adresse e-mail', blank=True)
-    phone_number = models.CharField(max_length=16, blank=True, default='',
-                                    verbose_name='Numéro de téléphone')
-    address = models.TextField(blank=True, default='', verbose_name='Adresse')
-    notes = models.TextField(blank=True, default='')
-
-    @property
-    def adhesion(self):
-        ctype = ContentType.objects.get_for_model(self)
-        try:
-            return Adhesion.objects.get(adherent_type=ctype, adherent_id=self.pk)
-        except Adhesion.DoesNotExist:
-            return None
-
-    class Meta:
-        verbose_name = 'personne morale'
-        verbose_name_plural = 'personnes morales'
-
-    def __str__(self):
-        return self.social_reason
+            return 'ADT%d (%s)' % (self.id, self.adherent)

+ 16 - 0
adhesions/signals.py

@@ -0,0 +1,16 @@
+from django.dispatch import receiver
+from django.db.models.signals import post_save
+
+from .models import User, Corporation, Adhesion
+
+
+@receiver(post_save, sender=User, dispatch_uid='create_user_adhesion')
+def create_user_adhesion(sender, instance, created, **kwargs):
+    if created:
+        Adhesion.objects.create(user=instance)
+
+
+@receiver(post_save, sender=Corporation, dispatch_uid='create_corporation_adhesion')
+def create_corporation_adhesion(sender, instance, created, **kwargs):
+    if created:
+        Adhesion.objects.create(corporation=instance)

+ 1 - 1
services/admin.py

@@ -156,7 +156,7 @@ ends_resource.short_description = 'Terminer les allocations sélectionnées'
 
 class ServiceAdmin(admin.ModelAdmin):
     list_display = ('id', 'get_adhesion_link', 'get_adherent_link', 'service_type', 'label', 'active')
-    list_select_related = ('adhesion',) # to reduce database requests
+    list_select_related = ('adhesion', 'adhesion__user', 'adhesion__user__profile', 'adhesion__corporation', 'service_type')
     list_filter = (
         'active',
         ('service_type', admin.RelatedOnlyFieldListFilter),