forked from DGNum/gestioCOF
cleanup et nouvelle implem de custommail
This commit is contained in:
parent
b9c2efaf0e
commit
298015285a
6 changed files with 120 additions and 150 deletions
|
@ -8,7 +8,6 @@ from datetime import timedelta
|
|||
|
||||
from django import forms
|
||||
from django.forms.models import BaseInlineFormSet
|
||||
from django.db.models import Q
|
||||
from django.utils import timezone
|
||||
from bda.models import Attribution, Spectacle
|
||||
|
||||
|
|
102
bda/models.py
102
bda/models.py
|
@ -1,13 +1,9 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import calendar
|
||||
import random
|
||||
from datetime import timedelta
|
||||
from custommail.utils import send_custom_mail, send_mass_custom_mail
|
||||
from custommail.shortcuts import send_custom_mail, send_mass_custom_mail
|
||||
|
||||
from django.contrib.sites.models import Site
|
||||
from django.db import models
|
||||
|
@ -105,18 +101,14 @@ class Spectacle(models.Model):
|
|||
# members[0] = ['BdA', 1, 'bda@ens.fr']
|
||||
# members[-1] = ['BdA', 2, 'bda@ens.fr']
|
||||
# On écrit un mail personnalisé à chaque participant
|
||||
mails_data = [
|
||||
(
|
||||
member[0].email,
|
||||
{'member': member[0],'nb_attr': member[1], 'show': self}
|
||||
)
|
||||
datatuple = [(
|
||||
'bda-rappel',
|
||||
{'member': member[0], 'nb_attr': member[1], 'show': self},
|
||||
settings.MAIL_DATA['rappels']['FROM'],
|
||||
[member[0].email])
|
||||
for member in members.values()
|
||||
]
|
||||
send_mass_custom_mail(
|
||||
'bda-rappel',
|
||||
mails_data,
|
||||
from_email=settings.MAIL_DATA['rappels']['FROM']
|
||||
)
|
||||
send_mass_custom_mail(datatuple)
|
||||
# On enregistre le fait que l'envoi a bien eu lieu
|
||||
self.rappel_sent = timezone.now()
|
||||
self.save()
|
||||
|
@ -252,23 +244,19 @@ class SpectacleRevente(models.Model):
|
|||
BdA-Revente à tous les intéressés.
|
||||
"""
|
||||
inscrits = self.attribution.spectacle.subscribed.select_related('user')
|
||||
mails_data = [
|
||||
(
|
||||
participant.user.email,
|
||||
{
|
||||
'member': participant.user,
|
||||
'show': self.attribution.spectacle,
|
||||
'revente': self,
|
||||
'site': Site.objects.get_current()
|
||||
}
|
||||
)
|
||||
datatuple = [(
|
||||
'bda-revente',
|
||||
{
|
||||
'member': participant.user,
|
||||
'show': self.attribution.spectacle,
|
||||
'revente': self,
|
||||
'site': Site.objects.get_current()
|
||||
},
|
||||
settings.MAIL_DATA['revente']['FROM'],
|
||||
[participant.user.email])
|
||||
for participant in inscrits
|
||||
]
|
||||
send_mass_custom_mail(
|
||||
"bda-revente",
|
||||
mails_data,
|
||||
from_email=settings.MAIL_DATA['revente']['FROM'],
|
||||
)
|
||||
send_mass_custom_mail(datatuple)
|
||||
self.notif_sent = True
|
||||
self.save()
|
||||
|
||||
|
@ -278,22 +266,18 @@ class SpectacleRevente(models.Model):
|
|||
leur indiquer qu'il est désormais disponible au shotgun.
|
||||
"""
|
||||
inscrits = self.attribution.spectacle.subscribed.select_related('user')
|
||||
mails_data = [
|
||||
(
|
||||
participant.user.email,
|
||||
{
|
||||
'member': participant.user,
|
||||
'show': self.attribution.spectacle,
|
||||
'site': Site.objects.get_current(),
|
||||
}
|
||||
)
|
||||
datatuple = [(
|
||||
'bda-shotgun',
|
||||
{
|
||||
'member': participant.user,
|
||||
'show': self.attribution.spectacle,
|
||||
'site': Site.objects.get_current(),
|
||||
},
|
||||
settings.MAIL_DATA['revente']['FROM'],
|
||||
[participant.user.email])
|
||||
for participant in inscrits
|
||||
]
|
||||
send_mass_custom_mail(
|
||||
"bda-shotgun",
|
||||
mails_data,
|
||||
from_email=settings.MAIL_DATA['revente']['FROM']
|
||||
)
|
||||
send_mass_custom_mail(datatuple)
|
||||
self.notif_sent = True
|
||||
# Flag inutile, sauf si l'horloge interne merde
|
||||
self.tirage_done = True
|
||||
|
@ -320,35 +304,31 @@ class SpectacleRevente(models.Model):
|
|||
'show': spectacle,
|
||||
}
|
||||
send_custom_mail(
|
||||
winner.user.email,
|
||||
'bda-revente-winner',
|
||||
[winner.user.email],
|
||||
context=context,
|
||||
from_email=settings.MAIL_DATA['revente']['FROM']
|
||||
)
|
||||
send_custom_mail(
|
||||
seller.user.email,
|
||||
'bda-revente-seller',
|
||||
[seller.user.email],
|
||||
context=context,
|
||||
from_email=settings.MAIL_DATA['revente']['FROM']
|
||||
)
|
||||
|
||||
# Envoie un mail aux perdants
|
||||
mails_data = [
|
||||
(
|
||||
inscrit.user.email,
|
||||
{
|
||||
'acheteur': inscrit.user,
|
||||
'vendeur': seller.user,
|
||||
'show': spectacle
|
||||
}
|
||||
)
|
||||
for inscrit in inscrits if inscrit == winner
|
||||
]
|
||||
send_mass_custom_mail(
|
||||
datatuple = [(
|
||||
'bda-revente-loser',
|
||||
mails_data,
|
||||
from_email=settings.MAIL_DATA['revente']['FROM']
|
||||
)
|
||||
{
|
||||
'acheteur': inscrit.user,
|
||||
'vendeur': seller.user,
|
||||
'show': spectacle
|
||||
},
|
||||
settings.MAIL_DATA['revente']['FROM'],
|
||||
[inscrit.user.email])
|
||||
for inscrit in inscrits if inscrit != winner
|
||||
]
|
||||
send_mass_custom_mail(datatuple)
|
||||
# Si personne ne veut de la place, elle part au shotgun
|
||||
else:
|
||||
self.shotgun = True
|
||||
|
|
85
bda/views.py
85
bda/views.py
|
@ -5,7 +5,13 @@ from __future__ import print_function
|
|||
from __future__ import unicode_literals
|
||||
|
||||
import random
|
||||
from custommail.utils import send_mass_custom_mail, send_custom_mail
|
||||
import hashlib
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
from custommail.shortcuts import (
|
||||
send_mass_custom_mail, send_custom_mail, render_custom_mail
|
||||
)
|
||||
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
@ -16,15 +22,10 @@ from django.forms.models import inlineformset_factory
|
|||
from django.http import HttpResponseBadRequest, HttpResponseRedirect
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.conf import settings
|
||||
import hashlib
|
||||
|
||||
from django.template import loader
|
||||
from django.utils import timezone
|
||||
from django.views.generic.list import ListView
|
||||
|
||||
import time
|
||||
from datetime import timedelta
|
||||
|
||||
from gestioncof.decorators import cof_required, buro_required
|
||||
from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\
|
||||
Tirage, SpectacleRevente
|
||||
|
@ -230,8 +231,8 @@ def do_tirage(request, tirage_id):
|
|||
# À partir d'ici, le tirage devient effectif
|
||||
Attribution.objects.filter(spectacle__tirage=tirage_elt).delete()
|
||||
tirage_elt.tokens += "%s\n\"\"\"%s\"\"\"\n" % (
|
||||
timezone.now().strftime("%y-%m-%d %H:%M:%S"),
|
||||
form.cleaned_data['token'])
|
||||
timezone.now().strftime("%y-%m-%d %H:%M:%S"),
|
||||
form.cleaned_data['token'])
|
||||
tirage_elt.enable_do_tirage = False
|
||||
tirage_elt.save()
|
||||
Attribution.objects.bulk_create([
|
||||
|
@ -276,7 +277,7 @@ def revente(request, tirage_id):
|
|||
resellform = ResellForm(participant, request.POST, prefix='resell')
|
||||
annulform = AnnulForm(participant, prefix='annul')
|
||||
if resellform.is_valid():
|
||||
mails_data = []
|
||||
datatuple = []
|
||||
attributions = resellform.cleaned_data["attributions"]
|
||||
with transaction.atomic():
|
||||
for attribution in attributions:
|
||||
|
@ -296,13 +297,13 @@ def revente(request, tirage_id):
|
|||
'show': attribution.spectacle,
|
||||
'revente': revente
|
||||
}
|
||||
mails_data.append(participant.user.email, context)
|
||||
datatuple.append((
|
||||
'bda-revente-new', context,
|
||||
settings.MAIL_DATA['revente']['FROM'],
|
||||
[participant.user.email]
|
||||
))
|
||||
revente.save()
|
||||
send_mass_custom_mail(
|
||||
'bda-revente-new',
|
||||
mails_data,
|
||||
from_email=settings.MAIL_DATA['revente']['FROM']
|
||||
)
|
||||
send_mass_custom_mail(datatuple)
|
||||
# On annule une revente
|
||||
elif 'annul' in request.POST:
|
||||
annulform = AnnulForm(participant, request.POST, prefix='annul')
|
||||
|
@ -354,15 +355,15 @@ def revente(request, tirage_id):
|
|||
annulform = AnnulForm(participant, prefix='annul')
|
||||
|
||||
overdue = participant.attribution_set.filter(
|
||||
spectacle__date__gte=timezone.now(),
|
||||
revente__isnull=False,
|
||||
revente__seller=participant,
|
||||
revente__date__lte=timezone.now()-timedelta(hours=1)).filter(
|
||||
spectacle__date__gte=timezone.now(),
|
||||
revente__isnull=False,
|
||||
revente__seller=participant,
|
||||
revente__date__lte=timezone.now()-timedelta(hours=1)).filter(
|
||||
Q(revente__soldTo__isnull=True) | Q(revente__soldTo=participant))
|
||||
sold = participant.attribution_set.filter(
|
||||
spectacle__date__gte=timezone.now(),
|
||||
revente__isnull=False,
|
||||
revente__soldTo__isnull=False)
|
||||
spectacle__date__gte=timezone.now(),
|
||||
revente__isnull=False,
|
||||
revente__soldTo__isnull=False)
|
||||
|
||||
return render(request, "bda-revente.html",
|
||||
{'tirage': tirage, 'overdue': overdue, "sold": sold,
|
||||
|
@ -372,7 +373,7 @@ def revente(request, tirage_id):
|
|||
@login_required
|
||||
def revente_interested(request, revente_id):
|
||||
revente = get_object_or_404(SpectacleRevente, id=revente_id)
|
||||
participant, created = Participant.objects.get_or_create(
|
||||
participant, _ = Participant.objects.get_or_create(
|
||||
user=request.user, tirage=revente.attribution.spectacle.tirage)
|
||||
if (timezone.now() < revente.date + timedelta(hours=1)) or revente.shotgun:
|
||||
return render(request, "bda-wrongtime.html",
|
||||
|
@ -387,8 +388,8 @@ def revente_interested(request, revente_id):
|
|||
@login_required
|
||||
def list_revente(request, tirage_id):
|
||||
tirage = get_object_or_404(Tirage, id=tirage_id)
|
||||
participant, created = Participant.objects.get_or_create(
|
||||
user=request.user, tirage=tirage)
|
||||
participant, _ = Participant.objects.get_or_create(
|
||||
user=request.user, tirage=tirage)
|
||||
deja_revente = False
|
||||
success = False
|
||||
inscrit_revente = False
|
||||
|
@ -400,7 +401,7 @@ def list_revente(request, tirage_id):
|
|||
participant.save()
|
||||
for spectacle in choices:
|
||||
qset = SpectacleRevente.objects.filter(
|
||||
attribution__spectacle=spectacle)
|
||||
attribution__spectacle=spectacle)
|
||||
if qset.filter(shotgun=True, soldTo__isnull=True).exists():
|
||||
# Une place est disponible au shotgun, on suggère à
|
||||
# l'utilisateur d'aller la récupérer
|
||||
|
@ -422,24 +423,24 @@ def list_revente(request, tirage_id):
|
|||
success = True
|
||||
else:
|
||||
form = InscriptionReventeForm(
|
||||
tirage,
|
||||
initial={'spectacles': participant.choicesrevente.all()})
|
||||
tirage,
|
||||
initial={'spectacles': participant.choicesrevente.all()})
|
||||
|
||||
return render(request, "liste-reventes.html",
|
||||
{"form": form,
|
||||
"deja_revente": deja_revente, "success": success,
|
||||
"inscrit_revente": inscrit_revente})
|
||||
"deja_revente": deja_revente, "success": success,
|
||||
"inscrit_revente": inscrit_revente})
|
||||
|
||||
|
||||
@login_required
|
||||
def buy_revente(request, spectacle_id):
|
||||
spectacle = get_object_or_404(Spectacle, id=spectacle_id)
|
||||
tirage = spectacle.tirage
|
||||
participant, created = Participant.objects.get_or_create(
|
||||
user=request.user, tirage=tirage)
|
||||
participant, _ = Participant.objects.get_or_create(
|
||||
user=request.user, tirage=tirage)
|
||||
reventes = SpectacleRevente.objects.filter(
|
||||
attribution__spectacle=spectacle,
|
||||
soldTo__isnull=True)
|
||||
attribution__spectacle=spectacle,
|
||||
soldTo__isnull=True)
|
||||
|
||||
# Si l'utilisateur veut racheter une place qu'il est en train de revendre,
|
||||
# on supprime la revente en question.
|
||||
|
@ -464,8 +465,8 @@ def buy_revente(request, spectacle_id):
|
|||
'vendeur': revente.seller.user
|
||||
}
|
||||
send_custom_mail(
|
||||
revente.seller.user.email,
|
||||
'bda-buy-shotgun',
|
||||
[revente.seller.user.email],
|
||||
context=context,
|
||||
from_email='bda@ens.fr'
|
||||
)
|
||||
|
@ -482,13 +483,13 @@ def buy_revente(request, spectacle_id):
|
|||
def revente_shotgun(request, tirage_id):
|
||||
tirage = get_object_or_404(Tirage, id=tirage_id)
|
||||
spectacles = tirage.spectacle_set.filter(
|
||||
date__gte=timezone.now())
|
||||
date__gte=timezone.now())
|
||||
shotgun = []
|
||||
for spectacle in spectacles:
|
||||
reventes = SpectacleRevente.objects.filter(
|
||||
attribution__spectacle=spectacle,
|
||||
shotgun=True,
|
||||
soldTo__isnull=True)
|
||||
attribution__spectacle=spectacle,
|
||||
shotgun=True,
|
||||
soldTo__isnull=True)
|
||||
if reventes.exists():
|
||||
shotgun.append(spectacle)
|
||||
|
||||
|
@ -552,12 +553,12 @@ def unpaid(request, tirage_id):
|
|||
def send_rappel(request, spectacle_id):
|
||||
show = get_object_or_404(Spectacle, id=spectacle_id)
|
||||
# Mails d'exemples
|
||||
exemple_mail_1place = render_mail('bda-rappel', {
|
||||
exemple_mail_1place = render_custom_mail('bda-rappel', {
|
||||
'member': request.user,
|
||||
'show': show,
|
||||
'nb_attr': 1
|
||||
})
|
||||
exemple_mail_2place = render_mail('bda-rappel', {
|
||||
exemple_mail_2places = render_custom_mail('bda-rappel', {
|
||||
'member': request.user,
|
||||
'show': show,
|
||||
'nb_attr': 2
|
||||
|
@ -589,5 +590,5 @@ def descriptions_spectacles(request, tirage_id):
|
|||
shows_qs = shows_qs.filter(location__id=int(location_id))
|
||||
except ValueError:
|
||||
return HttpResponseBadRequest(
|
||||
"La variable GET 'location' doit contenir un entier")
|
||||
"La variable GET 'location' doit contenir un entier")
|
||||
return render(request, 'descriptions.html', {'shows': shows_qs.all()})
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from __future__ import division
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from custommail.utils import send_custom_mail, render_mail
|
||||
from datetime import datetime
|
||||
import base64
|
||||
import json
|
||||
from captcha.fields import ReCaptchaField
|
||||
from custommail.shortcuts import render_custom_mail
|
||||
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.core import mail
|
||||
from django.forms import ModelForm
|
||||
from django import forms
|
||||
from django.forms.models import inlineformset_factory, BaseInlineFormSet
|
||||
|
@ -14,7 +15,6 @@ from django.contrib.auth.models import User
|
|||
from django.views.generic import ListView
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from django.template import loader
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db.models import Min
|
||||
|
@ -26,12 +26,6 @@ from gestioncof.petits_cours_models import PetitCoursDemande, \
|
|||
from gestioncof.decorators import buro_required
|
||||
from gestioncof.shared import lock_table, unlock_tables
|
||||
|
||||
from captcha.fields import ReCaptchaField
|
||||
|
||||
from datetime import datetime
|
||||
import base64
|
||||
import json
|
||||
|
||||
|
||||
class DemandeListView(ListView):
|
||||
model = PetitCoursDemande
|
||||
|
@ -131,7 +125,7 @@ def _finalize_traitement(request, demande, proposals, proposed_for,
|
|||
proposed_for = proposed_for.items()
|
||||
attribdata = list(attribdata.items())
|
||||
proposed_mails = _generate_eleve_email(demande, proposed_for)
|
||||
mainmail = render_mail("petits-cours-mail-demandeur", {
|
||||
mainmail = render_custom_mail("petits-cours-mail-demandeur", {
|
||||
"proposals": proposals,
|
||||
"unsatisfied": unsatisfied,
|
||||
"extra":
|
||||
|
@ -148,7 +142,7 @@ def _finalize_traitement(request, demande, proposals, proposed_for,
|
|||
"mainmail": mainmail,
|
||||
"attribdata":
|
||||
base64.b64encode(json.dumps(attribdata)
|
||||
.encode('utf_8')),
|
||||
.encode('utf_8')),
|
||||
"redo": redo,
|
||||
"errors": errors,
|
||||
})
|
||||
|
@ -158,7 +152,7 @@ def _generate_eleve_email(demande, proposed_for):
|
|||
return [
|
||||
(
|
||||
user,
|
||||
render_mail('petit-cours-mail-eleve', {
|
||||
render_custom_mail('petit-cours-mail-eleve', {
|
||||
"demande": demande,
|
||||
"matieres": matieres
|
||||
})[1]
|
||||
|
@ -276,7 +270,7 @@ def _traitement_post(request, demande):
|
|||
proposals_list = proposals.items()
|
||||
proposed_for = proposed_for.items()
|
||||
proposed_mails = _generate_eleve_email(demande, proposed_for)
|
||||
mainmail = render_mail("petits-cours-mail-demandeur", {
|
||||
mainmail = render_custom_mail("petits-cours-mail-demandeur", {
|
||||
"proposals": proposals_list,
|
||||
"unsatisfied": unsatisfied,
|
||||
"extra": extra,
|
||||
|
@ -286,14 +280,14 @@ def _traitement_post(request, demande):
|
|||
replyto = settings.MAIL_DATA['petits_cours']['REPLYTO']
|
||||
mails_to_send = []
|
||||
for (user, msg) in proposed_mails:
|
||||
msg = EmailMessage("Petits cours ENS par le COF", msg,
|
||||
frommail, [user.email],
|
||||
[bccaddress], headers={'Reply-To': replyto})
|
||||
msg = mail.EmailMessage("Petits cours ENS par le COF", msg,
|
||||
frommail, [user.email],
|
||||
[bccaddress], headers={'Reply-To': replyto})
|
||||
mails_to_send.append(msg)
|
||||
mails_to_send.append(EmailMessage("Cours particuliers ENS", mainmail,
|
||||
frommail, [demande.email],
|
||||
[bccaddress],
|
||||
headers={'Reply-To': replyto}))
|
||||
mails_to_send.append(mail.EmailMessage("Cours particuliers ENS", mainmail,
|
||||
frommail, [demande.email],
|
||||
[bccaddress],
|
||||
headers={'Reply-To': replyto}))
|
||||
connection = mail.get_connection(fail_silently=True)
|
||||
connection.send_messages(mails_to_send)
|
||||
lock_table(PetitCoursAttributionCounter, PetitCoursAttribution, User)
|
||||
|
|
|
@ -9,10 +9,7 @@ from django.conf import settings
|
|||
from django_cas_ng.backends import CASBackend
|
||||
from django_cas_ng.utils import get_cas_client
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.contrib.auth.models import User as DjangoUser
|
||||
from django.db import connection
|
||||
from django.core.mail import send_mail
|
||||
from django.template import Template, Context
|
||||
|
||||
from gestioncof.models import CofProfile
|
||||
|
||||
|
@ -73,9 +70,9 @@ class COFCASBackend(CASBackend):
|
|||
def context_processor(request):
|
||||
'''Append extra data to the context of the given request'''
|
||||
data = {
|
||||
"user": request.user,
|
||||
"site": Site.objects.get_current(),
|
||||
}
|
||||
"user": request.user,
|
||||
"site": Site.objects.get_current(),
|
||||
}
|
||||
return data
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import unicodecsv
|
|||
import uuid
|
||||
from datetime import timedelta
|
||||
from icalendar import Calendar, Event as Vevent
|
||||
from custommail.utils import send_custom_mail
|
||||
from custommail.shortcuts import send_custom_mail
|
||||
|
||||
from django.shortcuts import redirect, get_object_or_404, render
|
||||
from django.http import Http404, HttpResponse, HttpResponseForbidden
|
||||
|
@ -439,7 +439,7 @@ def registration(request):
|
|||
profile = profile_form.save()
|
||||
if profile.is_cof and not was_cof:
|
||||
send_custom_mail(
|
||||
member.email, "welcome",
|
||||
"welcome", [member.email],
|
||||
context={'member': member},
|
||||
from_email='cof@ens.fr'
|
||||
)
|
||||
|
@ -465,21 +465,20 @@ def registration(request):
|
|||
current_registration.paid = \
|
||||
(form.cleaned_data['status'] == 'paid')
|
||||
current_registration.save()
|
||||
if form.event.title == "Mega 15" and created_reg:
|
||||
field = EventCommentField.objects.get(
|
||||
event=form.event, name="Commentaires")
|
||||
try:
|
||||
comments = EventCommentValue.objects.get(
|
||||
commentfield=field,
|
||||
registration=current_registration).content
|
||||
except EventCommentValue.DoesNotExist:
|
||||
comments = field.default
|
||||
# FIXME : il faut faire quelque chose de propre ici,
|
||||
# par exemple écrire un mail générique pour
|
||||
# l'inscription aux événements et/ou donner la
|
||||
# possibilité d'associer un mail aux événements
|
||||
# send_custom_mail(member, "mega",
|
||||
# {"remarques": comments})
|
||||
# if form.event.title == "Mega 15" and created_reg:
|
||||
# field = EventCommentField.objects.get(
|
||||
# event=form.event, name="Commentaires")
|
||||
# try:
|
||||
# comments = EventCommentValue.objects.get(
|
||||
# commentfield=field,
|
||||
# registration=current_registration).content
|
||||
# except EventCommentValue.DoesNotExist:
|
||||
# comments = field.default
|
||||
# FIXME : il faut faire quelque chose de propre ici,
|
||||
# par exemple écrire un mail générique pour
|
||||
# l'inscription aux événements et/ou donner la
|
||||
# possibilité d'associer un mail aux événements
|
||||
# send_custom_mail(...)
|
||||
# Enregistrement des inscriptions aux clubs
|
||||
member.clubs.clear()
|
||||
for club in clubs_form.cleaned_data['clubs']:
|
||||
|
|
Loading…
Reference in a new issue