From 5ebf258eabd083ac92bf73b5e5e9e1298bc23f9b Mon Sep 17 00:00:00 2001
From: Yohann D'ANELLO <yohann.danello@gmail.com>
Date: Mon, 4 May 2020 20:21:53 +0200
Subject: [PATCH] Add some forms

---
 apps/member/forms.py                        |  7 +++
 apps/member/urls.py                         |  6 +-
 apps/member/views.py                        | 39 ++++++++++--
 apps/tournament/forms.py                    | 44 +++++++++++++
 apps/tournament/models.py                   | 11 ++++
 apps/tournament/urls.py                     |  9 ++-
 apps/tournament/views.py                    | 52 ++++++++++++++--
 locale/fr/LC_MESSAGES/django.po             |  2 +-
 templates/member/my_account.html            | 14 +++++
 templates/member/tfjmuser_detail.html       | 69 +++++++++++++++++++++
 templates/tournament/add_organizer.html     | 11 ++++
 templates/tournament/team_detail.html       | 11 ++--
 templates/tournament/team_form.html         | 11 ++++
 templates/tournament/tournament_detail.html |  6 +-
 templates/tournament/tournament_form.html   | 11 ++++
 templates/tournament/tournament_list.html   |  4 +-
 tfjm/settings.py                            |  4 +-
 17 files changed, 285 insertions(+), 26 deletions(-)
 create mode 100644 apps/tournament/forms.py
 create mode 100644 templates/member/my_account.html
 create mode 100644 templates/member/tfjmuser_detail.html
 create mode 100644 templates/tournament/add_organizer.html
 create mode 100644 templates/tournament/team_form.html
 create mode 100644 templates/tournament/tournament_form.html

diff --git a/apps/member/forms.py b/apps/member/forms.py
index 6a9449f..e304e4e 100644
--- a/apps/member/forms.py
+++ b/apps/member/forms.py
@@ -1,4 +1,5 @@
 from django.contrib.auth.forms import UserCreationForm
+from django import forms
 from django.utils.translation import gettext_lazy as _
 
 from member.models import TFJMUser
@@ -37,3 +38,9 @@ class SignUpForm(UserCreationForm):
             'responsible_email',
             'description',
         )
+
+
+class TFJMUserForm(forms.ModelForm):
+    class Meta:
+        model = TFJMUser
+        fields = '__all__'
diff --git a/apps/member/urls.py b/apps/member/urls.py
index c918085..7a62cd1 100644
--- a/apps/member/urls.py
+++ b/apps/member/urls.py
@@ -1,13 +1,15 @@
 from django.urls import path
 from django.views.generic import RedirectView
 
-from .views import CreateUserView, ProfileListView, OrphanedProfileListView, OrganizersListView
+from .views import CreateUserView, MyAccountView, UserDetailView,\
+    ProfileListView, OrphanedProfileListView, OrganizersListView
 
 app_name = "member"
 
 urlpatterns = [
     path('signup/', CreateUserView.as_view(), name="signup"),
-    path("my-account/", RedirectView.as_view(pattern_name="index"), name="my_account"),
+    path("my-account/", MyAccountView.as_view(), name="my_account"),
+    path("information/<int:pk>/", UserDetailView.as_view(), name="information"),
     path("add-team/", RedirectView.as_view(pattern_name="index"), name="add_team"),
     path("join-team/", RedirectView.as_view(pattern_name="index"), name="join_team"),
     path("my-team/", RedirectView.as_view(pattern_name="index"), name="my_team"),
diff --git a/apps/member/views.py b/apps/member/views.py
index 6802b75..3cc1968 100644
--- a/apps/member/views.py
+++ b/apps/member/views.py
@@ -4,11 +4,11 @@ from django.db.models import Q
 from django.http import FileResponse
 from django.utils.translation import gettext_lazy as _
 from django.views import View
-from django.views.generic import CreateView
+from django.views.generic import CreateView, UpdateView, DetailView
 from django_tables2 import SingleTableView
 
 from tournament.views import AdminMixin
-from .forms import SignUpForm
+from .forms import SignUpForm, TFJMUserForm
 from .models import TFJMUser, Document
 from .tables import UserTable
 
@@ -19,6 +19,35 @@ class CreateUserView(CreateView):
     template_name = "registration/signup.html"
 
 
+class MyAccountView(LoginRequiredMixin, UpdateView):
+    model = TFJMUser
+    form_class = TFJMUserForm
+    template_name = "member/my_account.html"
+
+    def get_object(self, queryset=None):
+        return self.request.user
+
+
+class UserDetailView(LoginRequiredMixin, DetailView):
+    model = TFJMUser
+    form_class = TFJMUserForm
+    context_object_name = "user"
+
+    def dispatch(self, request, *args, **kwargs):
+        if not request.user.admin \
+                and (self.object.team is not None and request.user not in self.object.team.tournament.organizers)\
+                and self.request.user != self.object:
+            raise PermissionDenied
+        return super().dispatch(request, *args, **kwargs)
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+
+        context["title"] = str(self.object)
+
+        return context
+
+
 class DocumentView(LoginRequiredMixin, View):
     def get(self, request, *args, **kwargs):
         doc = Document.objects.get(file=self.kwargs["file"])
@@ -29,7 +58,7 @@ class DocumentView(LoginRequiredMixin, View):
         return FileResponse(doc.file, content_type="application/pdf")
 
 
-class ProfileListView(LoginRequiredMixin, AdminMixin, SingleTableView):
+class ProfileListView(AdminMixin, SingleTableView):
     model = TFJMUser
     queryset = TFJMUser.objects.order_by("role", "last_name", "first_name")
     table_class = UserTable
@@ -37,7 +66,7 @@ class ProfileListView(LoginRequiredMixin, AdminMixin, SingleTableView):
     extra_context = dict(title=_("All profiles"))
 
 
-class OrphanedProfileListView(LoginRequiredMixin, AdminMixin, SingleTableView):
+class OrphanedProfileListView(AdminMixin, SingleTableView):
     model = TFJMUser
     queryset = TFJMUser.objects.filter((Q(role="2coach") | Q(role="3participant")) & Q(team__isnull=True))\
         .order_by("role", "last_name", "first_name")
@@ -46,7 +75,7 @@ class OrphanedProfileListView(LoginRequiredMixin, AdminMixin, SingleTableView):
     extra_context = dict(title=_("Orphaned profiles"))
 
 
-class OrganizersListView(LoginRequiredMixin, AdminMixin, SingleTableView):
+class OrganizersListView(AdminMixin, SingleTableView):
     model = TFJMUser
     queryset = TFJMUser.objects.filter(Q(role="0admin") | Q(role="1volunteer"))\
         .order_by("role", "last_name", "first_name")
diff --git a/apps/tournament/forms.py b/apps/tournament/forms.py
new file mode 100644
index 0000000..37e2ec9
--- /dev/null
+++ b/apps/tournament/forms.py
@@ -0,0 +1,44 @@
+from django import forms
+from django.utils.translation import gettext_lazy as _
+
+from member.models import TFJMUser
+from tfjm.inputs import DatePickerInput, DateTimePickerInput, AmountInput
+from tournament.models import Tournament, Team
+
+
+class TournamentForm(forms.ModelForm):
+    class Meta:
+        model = Tournament
+        fields = '__all__'
+        widgets = {
+            "price": AmountInput(),
+            "date_start": DatePickerInput(),
+            "date_end": DatePickerInput(),
+            "date_inscription": DateTimePickerInput(),
+            "date_solutions": DateTimePickerInput(),
+            "date_syntheses": DateTimePickerInput(),
+        }
+
+
+class OrganizerForm(forms.ModelForm):
+    class Meta:
+        model = TFJMUser
+        fields = ('last_name', 'first_name', 'email', 'is_superuser',)
+
+    def save(self, commit=True):
+        user = self.instance
+        user.role = '0admin' if user.is_superuser else '1organizer'
+        super().save(commit)
+
+
+class TeamForm(forms.ModelForm):
+    class Meta:
+        model = Team
+        fields = ('name', 'trigram', 'tournament',)
+
+
+class JoinTeam(forms.Form):
+    access_code = forms.CharField(
+        label=_("Access code"),
+        max_length=6,
+    )
diff --git a/apps/tournament/models.py b/apps/tournament/models.py
index eeb94c2..6fcb286 100644
--- a/apps/tournament/models.py
+++ b/apps/tournament/models.py
@@ -2,6 +2,7 @@ import os
 from datetime import date
 
 from django.db import models
+from django.urls import reverse_lazy
 from django.utils.translation import gettext_lazy as _
 
 
@@ -145,10 +146,20 @@ class Team(models.Model):
     def encadrants(self):
         return self.users.all().filter(role="2coach")
 
+    @property
+    def linked_encadrants(self):
+        return ['<a href="{url}">'.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '</a>'
+                for user in self.encadrants]
+
     @property
     def participants(self):
         return self.users.all().filter(role="3participant")
 
+    @property
+    def linked_participants(self):
+        return ['<a href="{url}">'.format(url=reverse_lazy("member:information", args=(user.pk,))) + str(user) + '</a>'
+                for user in self.participants]
+
     class Meta:
         verbose_name = _("team")
         verbose_name_plural = _("teams")
diff --git a/apps/tournament/urls.py b/apps/tournament/urls.py
index 4d03d7f..f1d4800 100644
--- a/apps/tournament/urls.py
+++ b/apps/tournament/urls.py
@@ -1,16 +1,19 @@
 from django.urls import path
 from django.views.generic import RedirectView
 
-from .views import TournamentListView, TournamentDetailView, TeamDetailView, SolutionsView, SolutionsOrgaListView
+from .views import TournamentListView, TournamentCreateView, TournamentDetailView, TournamentUpdateView,\
+    TeamDetailView, TeamUpdateView, AddOrganizerView, SolutionsView, SolutionsOrgaListView
 
 app_name = "tournament"
 
 urlpatterns = [
     path('list/', TournamentListView.as_view(), name="list"),
-    path("add/", RedirectView.as_view(pattern_name="index"), name="add"),
+    path("add/", TournamentCreateView.as_view(), name="add"),
     path('<int:pk>/', TournamentDetailView.as_view(), name="detail"),
+    path('<int:pk>/update/', TournamentUpdateView.as_view(), name="update"),
     path('team/<int:pk>/', TeamDetailView.as_view(), name="team_detail"),
-    path("add-organizer/", RedirectView.as_view(pattern_name="index"), name="add_organizer"),
+    path('team/<int:pk>/update/', TeamUpdateView.as_view(), name="team_update"),
+    path("add-organizer/", AddOrganizerView.as_view(), name="add_organizer"),
     path("solutions/", SolutionsView.as_view(), name="solutions"),
     path("all-solutions/", SolutionsOrgaListView.as_view(), name="all_solutions"),
     path("syntheses/", RedirectView.as_view(pattern_name="index"), name="syntheses"),
diff --git a/apps/tournament/views.py b/apps/tournament/views.py
index 041d29e..397b1a0 100644
--- a/apps/tournament/views.py
+++ b/apps/tournament/views.py
@@ -5,23 +5,26 @@ from django.contrib.auth.mixins import LoginRequiredMixin
 from django.core.exceptions import PermissionDenied
 from django.db.models import Q
 from django.http import HttpResponse
+from django.shortcuts import redirect
+from django.urls import reverse_lazy
 from django.utils.translation import gettext_lazy as _
-from django.views.generic import DetailView
+from django.views.generic import DetailView, CreateView, UpdateView
 from django_tables2.views import SingleTableView
 
 from member.models import TFJMUser, Solution
+from .forms import TournamentForm, OrganizerForm, TeamForm
 from .models import Tournament, Team
 from .tables import TournamentTable, TeamTable, SolutionTable
 
 
-class AdminMixin(object):
+class AdminMixin(LoginRequiredMixin):
     def dispatch(self, request, *args, **kwargs):
         if not request.user.admin:
             raise PermissionDenied
         return super().dispatch(request, *args, **kwargs)
 
 
-class TeamMixin(object):
+class TeamMixin(LoginRequiredMixin):
     def dispatch(self, request, *args, **kwargs):
         if not request.user.team:
             raise PermissionDenied
@@ -47,6 +50,15 @@ class TournamentListView(SingleTableView):
         return context
 
 
+class TournamentCreateView(AdminMixin, CreateView):
+    model = Tournament
+    form_class = TournamentForm
+    extra_context = dict(title=_("Add tournament"),)
+
+    def get_success_url(self):
+        return reverse_lazy('tournament:detail', args=(self.object.pk,))
+
+
 class TournamentDetailView(DetailView):
     model = Tournament
 
@@ -71,6 +83,15 @@ class TournamentDetailView(DetailView):
         return context
 
 
+class TournamentUpdateView(AdminMixin, UpdateView):
+    model = Tournament
+    form_class = TournamentForm
+    extra_context = dict(title=_("Update tournament"),)
+
+    def get_success_url(self):
+        return reverse_lazy('tournament:detail', args=(self.object.pk,))
+
+
 class TeamDetailView(LoginRequiredMixin, DetailView):
     model = Team
 
@@ -97,6 +118,9 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
                 .format(_("Solutions for team {team}.zip")
                         .format(team=str(team)).replace(" ", "%20"))
             return resp
+        elif "delete" in request.POST:
+            team.delete()
+            return redirect('tournament:detail', pk=team.tournament.pk)
 
         return self.get(request, *args, **kwargs)
 
@@ -108,7 +132,25 @@ class TeamDetailView(LoginRequiredMixin, DetailView):
         return context
 
 
-class SolutionsView(LoginRequiredMixin, TeamMixin, SingleTableView):
+class TeamUpdateView(LoginRequiredMixin, UpdateView):
+    model = Team
+    form_class = TeamForm
+    extra_context = dict(title=_("Udpate team"),)
+
+    def dispatch(self, request, *args, **kwargs):
+        if not request.user.admin and self.request.user not in self.get_object().tournament.organizers:
+            raise PermissionDenied
+        return super().dispatch(request, *args, **kwargs)
+
+
+class AddOrganizerView(AdminMixin, CreateView):
+    model = TFJMUser
+    form_class = OrganizerForm
+    extra_context = dict(title=_("Add organizer"),)
+    template_name = "tournament/add_organizer.html"
+
+
+class SolutionsView(TeamMixin, SingleTableView):
     model = Solution
     table_class = SolutionTable
     template_name = "tournament/solutions_list.html"
@@ -149,7 +191,7 @@ class SolutionsView(LoginRequiredMixin, TeamMixin, SingleTableView):
         return qs.order_by('team__tournament__date_start', 'team__tournament__name', 'team__trigram', 'problem',)
 
 
-class SolutionsOrgaListView(LoginRequiredMixin, AdminMixin, SingleTableView):
+class SolutionsOrgaListView(AdminMixin, SingleTableView):
     model = Solution
     table_class = SolutionTable
     template_name = "tournament/solutions_orga_list.html"
diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po
index 014f63e..03f2b72 100644
--- a/locale/fr/LC_MESSAGES/django.po
+++ b/locale/fr/LC_MESSAGES/django.po
@@ -442,7 +442,7 @@ msgstr "Liste des tournois"
 
 #: apps/tournament/views.py:56
 msgid "Tournament of {name}"
-msgstr "Tournoi de {user}"
+msgstr "Tournoi de {name}"
 
 #: apps/tournament/views.py:97 apps/tournament/views.py:131
 #, python-brace-format
diff --git a/templates/member/my_account.html b/templates/member/my_account.html
new file mode 100644
index 0000000..9031a48
--- /dev/null
+++ b/templates/member/my_account.html
@@ -0,0 +1,14 @@
+{% extends "base.html" %}
+
+{% load i18n crispy_forms_filters %}
+
+{% block content %}
+    <form method="post">
+        {{ form|crispy }}
+        <input type="submit" class="btn btn-primary btn-block" value="{% trans "Submit" %}">
+    </form>
+
+    <hr>
+
+    <a class="btn btn-secondary btn-block" href="{% url "password_change" %}">{% trans "Update my password" %}</a>
+{% endblock %}
diff --git a/templates/member/tfjmuser_detail.html b/templates/member/tfjmuser_detail.html
new file mode 100644
index 0000000..486d172
--- /dev/null
+++ b/templates/member/tfjmuser_detail.html
@@ -0,0 +1,69 @@
+{% extends "base.html" %}
+
+{% load getconfig i18n django_tables2 static %}
+
+{% block content %}
+    <div class="card bg-light shadow">
+        <div class="card-header text-center">
+            <h4>{{ user }}</h4>
+        </div>
+        <div class="card-body">
+            <dl class="row">
+                <dt class="col-xl-6 text-right">{% trans 'role'|capfirst %}</dt>
+                <dd class="col-xl-6">{{ user.get_role_display }}</dd>
+
+                <dt class="col-xl-6 text-right">{% trans 'team'|capfirst %}</dt>
+                <dd class="col-xl-6"><a href="{% url "tournament:team_detail" pk=user.team.pk %}">{{ user.team }}</a></dd>
+
+                <dt class="col-xl-6 text-right">{% trans 'birth date'|capfirst %}</dt>
+                <dd class="col-xl-6">{{ user.birth_date }}</dd>
+
+                <dt class="col-xl-6 text-right">{% trans 'gender'|capfirst %}</dt>
+                <dd class="col-xl-6">{{ user.get_gender_display }}</dd>
+
+                <dt class="col-xl-6 text-right">{% trans 'address'|capfirst %}</dt>
+                <dd class="col-xl-6">{{ user.address }}, {{ user.postal_code }}, {{ user.city }}{% if user.country != "France" %}, {{ user.country }}{% endif %}</dd>
+
+                <dt class="col-xl-6 text-right">{% trans 'email'|capfirst %}</dt>
+                <dd class="col-xl-6"><a href="mailto:{{ user.email }}">{{ user.email }}</a></dd>
+
+                <dt class="col-xl-6 text-right">{% trans 'phone number'|capfirst %}</dt>
+                <dd class="col-xl-6">{{ user.phone_number }}</dd>
+
+                {% if user.role == '3participant' %}
+                    <dt class="col-xl-6 text-right">{% trans 'school'|capfirst %}</dt>
+                    <dd class="col-xl-6">{{ user.school }}</dd>
+
+                    <dt class="col-xl-6 text-right">{% trans 'class'|capfirst %}</dt>
+                    <dd class="col-xl-6">{{ user.get_student_class_display }}</dd>
+
+                    {% if user.responsible_name %}
+                        <dt class="col-xl-6 text-right">{% trans 'responsible name'|capfirst %}</dt>
+                        <dd class="col-xl-6">{{ user.responsible_name }}</dd>
+                    {% endif %}
+
+                    {% if user.responsible_phone %}
+                        <dt class="col-xl-6 text-right">{% trans 'responsible phone'|capfirst %}</dt>
+                        <dd class="col-xl-6">{{ user.responsible_phone }}</dd>
+                    {% endif %}
+
+                    {% if user.responsible_email %}
+                        <dt class="col-xl-6 text-right">{% trans 'responsible email'|capfirst %}</dt>
+                        <dd class="col-xl-6"><a href="{{ user.responsible_email }}">{{ user.responsible_email }}</a></dd>
+                    {% endif %}
+                {% endif %}
+
+                {% if user.role == '2coach' %}
+                    <dt class="col-xl-6 text-right">{% trans 'description'|capfirst %}</dt>
+                    <dd class="col-xl-6">{{ user.description }}</dd>
+                {% endif %}
+            </dl>
+        </div>
+    </div>
+
+    <hr>
+
+    <h4>{% trans "Documents" %}</h4>
+
+    {# TODO Display documents #}
+{% endblock %}
diff --git a/templates/tournament/add_organizer.html b/templates/tournament/add_organizer.html
new file mode 100644
index 0000000..21daee8
--- /dev/null
+++ b/templates/tournament/add_organizer.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% load i18n crispy_forms_filters %}
+
+{% block content %}
+    <form method="post">
+        {% csrf_token %}
+        {{ form|crispy }}
+        <input type="submit" class="btn btn-primary btn-block" value="{% trans "Submit" %}">
+    </form>
+{% endblock %}
diff --git a/templates/tournament/team_detail.html b/templates/tournament/team_detail.html
index 3d1ae5b..056dff1 100644
--- a/templates/tournament/team_detail.html
+++ b/templates/tournament/team_detail.html
@@ -19,18 +19,21 @@
                 <dd class="col-xl-6">{{ team.tournament }}</dd>
 
                 <dt class="col-xl-6 text-right">{% trans 'coachs'|capfirst %}</dt>
-                <dd class="col-xl-6">{{ team.encadrants.all|join:", " }}</dd>
+                <dd class="col-xl-6">{% autoescape off %}{{ team.linked_encadrants|join:", " }}{% endautoescape %}</dd>
 
                 <dt class="col-xl-6 text-right">{% trans 'participants'|capfirst %}</dt>
-                <dd class="col-xl-6">{{ team.participants.all|join:", " }}</dd>
+                <dd class="col-xl-6">{% autoescape off %}{{ team.linked_participants|join:", " }}{% endautoescape %}</dd>
             </dl>
         </div>
 
         {% if user.admin or user in team.tournament.organizers.all %}
             <div class="card-footer text-center">
-                <button class="btn btn-secondary">{% trans "Edit team" %}</button>
+                <a href="{% url "tournament:team_update" pk=team.pk %}"><button class="btn btn-secondary">{% trans "Edit team" %}</button></a>
                 {% if user.admin and team.invalid %}
-                    <button class="btn btn-danger">{% trans "Delete team" %}</button>
+                    <form method="post">
+                        {% csrf_token %}
+                        <button name="delete" class="btn btn-danger">{% trans "Delete team" %}</button>
+                    </form>
                 {% endif %}
             </div>
         {% endif %}
diff --git a/templates/tournament/team_form.html b/templates/tournament/team_form.html
new file mode 100644
index 0000000..21daee8
--- /dev/null
+++ b/templates/tournament/team_form.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% load i18n crispy_forms_filters %}
+
+{% block content %}
+    <form method="post">
+        {% csrf_token %}
+        {{ form|crispy }}
+        <input type="submit" class="btn btn-primary btn-block" value="{% trans "Submit" %}">
+    </form>
+{% endblock %}
diff --git a/templates/tournament/tournament_detail.html b/templates/tournament/tournament_detail.html
index 5eb0062..d5095da 100644
--- a/templates/tournament/tournament_detail.html
+++ b/templates/tournament/tournament_detail.html
@@ -39,15 +39,15 @@
 
             {% if user.is_authenticated and user.admin %}
                 <div class="alert alert-info">
-                    <a href="mailto:contact@tfm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ team_users_emails|join:"," }}">{% trans "Send a mail to all people in this tournament" %}</a><br>
-                    <a href="mailto:contact@tfm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ valid_team_users_emails|join:"," }}">{% trans "Send a mail to all people in this tournament that are in a valid team" %}</a>
+                    <a href="mailto:contact@tfjm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ team_users_emails|join:"," }}">{% trans "Send a mail to all people in this tournament" %}</a><br>
+                    <a href="mailto:contact@tfjm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ valid_team_users_emails|join:"," }}">{% trans "Send a mail to all people in this tournament that are in a valid team" %}</a>
                 </div>
             {% endif %}
         </div>
 
         {% if user.admin or user in tournament.organizers.all %}
             <div class="card-footer text-center">
-                <button class="btn btn-secondary">{% trans "Edit tournament" %}</button>
+                <a href="{% url "tournament:update" pk=tournament.pk %}"><button class="btn btn-secondary">{% trans "Edit tournament" %}</button></a>
             </div>
         {% endif %}
     </div>
diff --git a/templates/tournament/tournament_form.html b/templates/tournament/tournament_form.html
new file mode 100644
index 0000000..21daee8
--- /dev/null
+++ b/templates/tournament/tournament_form.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% load i18n crispy_forms_filters %}
+
+{% block content %}
+    <form method="post">
+        {% csrf_token %}
+        {{ form|crispy }}
+        <input type="submit" class="btn btn-primary btn-block" value="{% trans "Submit" %}">
+    </form>
+{% endblock %}
diff --git a/templates/tournament/tournament_list.html b/templates/tournament/tournament_list.html
index 8811241..27b9835 100644
--- a/templates/tournament/tournament_list.html
+++ b/templates/tournament/tournament_list.html
@@ -5,8 +5,8 @@
 {% block content %}
     {% if user.is_authenticated and user.admin %}
         <div class="alert alert-info">
-            <a href="mailto:contact@tfm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ team_users_emails|join:"," }}">{% trans "Send a mail to all people that are in a team" %}</a><br>
-            <a href="mailto:contact@tfm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ valid_team_users_emails|join:"," }}">{% trans "Send a mail to all people that are in a valid team" %}</a>
+            <a href="mailto:contact@tfjm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ team_users_emails|join:"," }}">{% trans "Send a mail to all people that are in a team" %}</a><br>
+            <a href="mailto:contact@tfjm.org?subject=TFJM²%20{{ "TFJM_YEAR"|get_env }}&bcc={{ valid_team_users_emails|join:"," }}">{% trans "Send a mail to all people that are in a valid team" %}</a>
         </div>
     {% endif %}
     {% render_table table %}
diff --git a/tfjm/settings.py b/tfjm/settings.py
index 7b855e9..3cd70cf 100644
--- a/tfjm/settings.py
+++ b/tfjm/settings.py
@@ -89,6 +89,8 @@ TEMPLATES = [
     },
 ]
 
+FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'
+
 WSGI_APPLICATION = 'tfjm.wsgi.application'
 
 
@@ -150,7 +152,7 @@ LANGUAGES = [
     ('fr', _('French')),
 ]
 
-TIME_ZONE = 'UTC'
+TIME_ZONE = 'Europe/Paris'
 
 USE_I18N = True