Generic registration view

This commit is contained in:
Martin Pépin 2017-06-22 23:44:06 +01:00
parent f93a68b942
commit 0f491ef396
6 changed files with 200 additions and 19 deletions

View file

@ -1,12 +0,0 @@
{% extends "base_title.html" %}
{% block realcontent %}
<h2>Inscription d'un nouveau membre</h2>
{% if success %}
<p class="success">L'inscription de {{ member.first_name }} {{ member.last_name }} (<tt>{{ member.username }}</tt>) a été enregistrée avec succès.
{% if member.profile.is_cof %}Il est désormais membre du COF n°{{ member.profile.num }} !{% endif %}</p>
{% endif %}
<div id="form-placeholder">
{% include "cof/registration_form.html" %}
</div>
{% endblock %}

View file

@ -4,6 +4,10 @@ from django.contrib.auth.models import User
from .models import Profile from .models import Profile
# ---
# Profile edition
# ---
class UserForm(forms.ModelForm): class UserForm(forms.ModelForm):
class Meta: class Meta:
model = User model = User
@ -14,3 +18,48 @@ class ProfileForm(forms.ModelForm):
class Meta: class Meta:
model = Profile model = Profile
fields = ["phone", "departement"] fields = ["phone", "departement"]
# ---
# Registration
# ---
class UserRegistrationForm(forms.ModelForm):
passwd1 = forms.CharField(
label="Mot de passe",
widget=forms.PasswordInput,
required=False,
)
passwd2 = forms.CharField(
label="Confirmation de mot de passe",
widget=forms.PasswordInput,
required=False,
)
def clean_passwd2(self):
passwd1 = self.cleaned_data["passwd1"]
passwd2 = self.cleaned_data["passwd2"]
if passwd1 and passwd2:
if passwd1 != passwd2:
raise forms.ValidationError("Mots de passes différents")
return passwd2
def save(self, commit=True, *args, **kwargs):
user = super().save(commit, *args, **kwargs)
if self.cleaned_data["passwd2"]:
user.set_password(self.cleaned_data["passwd2"])
if commit:
user.save()
return user
class Meta:
model = User
fields = ["username", "first_name", "last_name", "email"]
class ProfileRegistrationForm(forms.ModelForm):
class Meta:
model = Profile
fields = [
"login_clipper", "phone", "occupation", "departement", "comments"
]

View file

@ -3,6 +3,21 @@ Locking/unlocking tools to prevent tables to be corrupted
""" """
from django.db import connection from django.db import connection
from django.contrib.auth.models import User
from django.conf import settings
def get_or_create_clipper(clipper, fullname=None):
user, created = User.objects.get_or_create(username=clipper)
if created:
user.email = settings.CAS_EMAIL_FORMAT % (clipper, )
if fullname:
bits = fullname.split(" ")
user.first_name = bits[0]
if len(bits) > 1:
user.last_name = " ".join(bits[1:])
user.save()
return (user, created)
def lock_table(*models): def lock_table(*models):

View file

@ -4,14 +4,18 @@
{% block page_size %}col-sm-8{% endblock %} {% block page_size %}col-sm-8{% endblock %}
{% block extra_head %} {% block extra_head %}
<script src="{% static "autocomplete_light/autocomplete.js" %}" type="text/javascript"></script> <script src="{% static "autocomplete_light/autocomplete.js" %}" type="text/javascript"></script>
{% endblock %} {% endblock %}
{% block realcontent %} {% block realcontent %}
<h2>Inscription d'un nouveau membre</h2> <h2>Inscription d'un nouveau membre</h2>
<input type="text" name="q" id="search_autocomplete" spellcheck="false" /> <input type="text" name="q" id="search_autocomplete" spellcheck="false" />
<div id="form-placeholder"></div> <div id="form-placeholder">
{% if user %}{% include "gestion/registration_form.html" %}{% endif %}
</div>
<div class="yourlabs-autocomplete"></div> <div class="yourlabs-autocomplete"></div>
<script type="text/javascript"> <script type="text/javascript">
// On attend que la page soit prête pour executer le code // On attend que la page soit prête pour executer le code
$(document).ready(function() { $(document).ready(function() {

View file

@ -7,7 +7,7 @@
{% else %} {% else %}
<h3>Inscription d'un nouveau compte (extérieur ?)</h3> <h3>Inscription d'un nouveau compte (extérieur ?)</h3>
{% endif %} {% endif %}
<form role="form" id="profile" method="post" action="{% url 'registration' %}"> <form role="form" id="profile" method="post" action="{{ page_url }}">
{% csrf_token %} {% csrf_token %}
<table> <table>
{{ user_form | bootstrap }} {{ user_form | bootstrap }}
@ -15,7 +15,7 @@
</table> </table>
<hr /> <hr />
<table> <table>
{{ cofprofile_form | bootstrap }} {{ extra_form | bootstrap }}
</table> </table>
{{ event_formset.management_form }} {{ event_formset.management_form }}
{% for event_form in event_formset %} {% for event_form in event_formset %}
@ -25,7 +25,7 @@
{{ event_form | bootstrap }} {{ event_form | bootstrap }}
</table> </table>
{% endfor %} {% endfor %}
{% if login_clipper or member %} {% if user %}
<input type="hidden" name="user_exists" value="1" /> <input type="hidden" name="user_exists" value="1" />
{% endif %} {% endif %}
<input type="submit" class="btn btn-primary pull-right" value="Enregistrer l'inscription" /> <input type="submit" class="btn btn-primary pull-right" value="Enregistrer l'inscription" />

View file

@ -4,16 +4,27 @@ The common views of the different organisations.
- Profile edition - Profile edition
""" """
from django.shortcuts import render, redirect from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.auth.views import ( from django.contrib.auth.views import (
login as django_login, logout as django_logout login as django_login, logout as django_logout
) )
from django.http import HttpResponseBadRequest
from django.shortcuts import render, redirect, get_object_or_404
from django.utils.translation import ugettext_lazy as _
from django.views.generic import TemplateView
from .forms import ProfileForm, UserForm from .forms import (
ProfileForm, UserForm, UserRegistrationForm, ProfileRegistrationForm
)
from .shared import get_or_create_clipper
# ---
# Authentcation
# ---
def login(request): def login(request):
if request.user.is_authenticated(): if request.user.is_authenticated():
return redirect("home") return redirect("home")
@ -54,6 +65,10 @@ def logout(request):
return django_logout(request) return django_logout(request)
# ---
# User management
# ---
@login_required @login_required
def profile(request): def profile(request):
success = False success = False
@ -71,3 +86,113 @@ def profile(request):
return render(request, "gestion/profile.html", return render(request, "gestion/profile.html",
{"user_form": user_form, "profile_form": profile_form, {"user_form": user_form, "profile_form": profile_form,
"success": success}) "success": success})
# TODO: send "Welcome" email
class RegistrationView(TemplateView):
user = None
form_class = None
form_only = False # TODO: explain this
page_url = "" # TODO: explain this
def get_form_kwargs(self, **kwargs):
return kwargs
# ---
# Template related code
# ---
@property
def template_name(self):
if self.form_only:
return "gestion/registration_form.html"
else:
return "gestion/registration.html"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
post_data = kwargs.pop("post_data", None)
user = self.user
context["user"] = user
context["page_url"] = self.page_url
context["user_form"] = UserRegistrationForm(
instance=user,
prefix="user",
data=post_data
)
context["profile_form"] = ProfileRegistrationForm(
instance=user.profile if user else None,
prefix="profile",
data=post_data
)
context["extra_form"] = self.form_class(**self.get_form_kwargs(
prefix="extra",
data=post_data,
))
return context
# ---
# Request processing
# ---
def get(self, request, username=""):
"""
The `user_type` GET parameter is used the following way:
- If not set, return empty forms.
- If set to "normal", assume the user exists.
- If set to, "clipper" create a user linked to a clipper account if a
user with the provided username doesn't exist.
The `fullname` GET parameter is only used to create new clipper users
"""
user_type, fullname = self.clean_GET(request.GET)
if user_type == "clipper":
self.user, _ = get_or_create_clipper(username, fullname)
elif user_type == "normal":
self.user = get_object_or_404(User, username=username)
context = self.get_context_data()
print(vars(self))
return super().render_to_response(context)
# def post(self, request, username):
def post(self, request):
# the `user_exists` POST parameter indicates that we should expect the
# user to be in the database already. Otherwise we return a 404 page.
# TODO: 404 is bad, prefer an "displayable" error
if "user_exists" in request.POST:
username = request.POST.get("user-username", "")
self.user = get_object_or_404(User, username=username)
context = self.get_context_data(
post_data=request.POST,
)
if all([context["user_form"].is_valid(),
context["profile_form"].is_valid(),
context["extra_form"].is_valid()]):
self.user = context["user_form"].save()
context["user"] = self.user
context["profile_form"].save()
context["extra_form"].save()
messages.success(
request,
_("L'inscription de %(fullname)s (<tt>%(username)s</tt>)"
" a été enregistrée avec succès")
% {"fullname": self.user.get_full_name(),
"username": self.user.username}
)
return super().render_to_response(context)
@staticmethod
def clean_GET(get_params):
allowed_user_types = {"normal", "clipper", None}
user_type = get_params.get("user_type")
if user_type not in allowed_user_types:
return HttpResponseBadRequest(
"Invalid value `{}` expected `({})`"
.format(user_type, "|".join(allowed_user_types))
)
fullname = get_params.get("fullname")
if fullname is not None:
fullname = str(fullname)
return user_type, fullname