From 5bd093a0a38ebbfe117e0981612be9ffe9e15a03 Mon Sep 17 00:00:00 2001 From: Dan Braghis <dan.braghis@torchbox.com> Date: Wed, 28 Feb 2018 11:16:03 +0000 Subject: [PATCH] Drop first/last names in favour of a single full_name field --- opentech/apply/users/forms.py | 26 ++++++++++ .../migrations/0004_drop_first_last_names.py | 37 ++++++++++++++ opentech/apply/users/models.py | 50 ++++++++++--------- .../templates/wagtailusers/users/create.html | 26 ++++++++++ .../templates/wagtailusers/users/edit.html | 26 ++++++++++ opentech/settings/base.py | 4 ++ 6 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 opentech/apply/users/forms.py create mode 100644 opentech/apply/users/migrations/0004_drop_first_last_names.py create mode 100644 opentech/apply/users/templates/wagtailusers/users/create.html create mode 100644 opentech/apply/users/templates/wagtailusers/users/edit.html diff --git a/opentech/apply/users/forms.py b/opentech/apply/users/forms.py new file mode 100644 index 000000000..2a2b97ffc --- /dev/null +++ b/opentech/apply/users/forms.py @@ -0,0 +1,26 @@ +from django import forms +from django.utils.translation import ugettext_lazy as _ + +from wagtail.wagtailusers.forms import UserEditForm, UserCreationForm + + +class CustomUserEditForm(UserEditForm): + full_name = forms.CharField(label=_("Full name"), required=True) + + def __init__(self, *args, **kwargs): + super(CustomUserEditForm, self).__init__(*args, **kwargs) + + # HACK: Wagtail admin doesn't work with custom User models that do not have first/last name. + self.fields['first_name'].widget = forms.HiddenInput(attrs={'value': f"fn{self.instance.pk}"}) + self.fields['last_name'].widget = forms.HiddenInput(attrs={'value': f"ln{self.instance.pk}"}) + + +class CustomUserCreationForm(UserCreationForm): + full_name = forms.CharField(label=_("Full name"), required=True) + + def __init__(self, *args, **kwargs): + super(CustomUserCreationForm, self).__init__(*args, **kwargs) + + # HACK: Wagtail admin doesn't work with custom User models that do not have first/last name. + self.fields['first_name'].widget = forms.HiddenInput(attrs={'value': f"fn{self.instance.pk}"}) + self.fields['last_name'].widget = forms.HiddenInput(attrs={'value': f"ln{self.instance.pk}"}) diff --git a/opentech/apply/users/migrations/0004_drop_first_last_names.py b/opentech/apply/users/migrations/0004_drop_first_last_names.py new file mode 100644 index 000000000..ec7153baa --- /dev/null +++ b/opentech/apply/users/migrations/0004_drop_first_last_names.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.8 on 2018-02-28 11:04 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0003_make_email_username'), + ] + + operations = [ + migrations.AlterModelOptions( + name='user', + options={'ordering': ['id']}, + ), + migrations.RemoveField( + model_name='user', + name='first_name', + ), + migrations.RemoveField( + model_name='user', + name='last_name', + ), + migrations.AddField( + model_name='user', + name='full_name', + field=models.CharField(blank=True, max_length=255, verbose_name='Full name'), + ), + migrations.AlterField( + model_name='user', + name='email', + field=models.EmailField(max_length=255, unique=True, verbose_name='email address'), + ), + ] diff --git a/opentech/apply/users/models.py b/opentech/apply/users/models.py index 26a0c2c35..e69cf921f 100644 --- a/opentech/apply/users/models.py +++ b/opentech/apply/users/models.py @@ -1,23 +1,10 @@ from django.db import models -from django.contrib.auth.models import AbstractUser, BaseUserManager +from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin +from django.utils import timezone from django.utils.translation import gettext_lazy as _ from .utils import send_activation_email - -def convert_full_name_to_parts(defaults): - full_name = defaults.pop('full_name', ' ') - if not full_name: - # full_name was None - full_name = ' ' - first_name, *last_name = full_name.split(' ') - if first_name: - defaults.update(first_name=first_name) - if last_name: - defaults.update(last_name=' '.join(last_name)) - return defaults - - class UserManager(BaseUserManager): use_in_migrations = True @@ -28,7 +15,6 @@ class UserManager(BaseUserManager): if not email: raise ValueError('The given email must be set') email = self.normalize_email(email) - extra_fields = convert_full_name_to_parts(extra_fields) user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) @@ -50,11 +36,6 @@ class UserManager(BaseUserManager): return self._create_user(email, password, **extra_fields) - def get_or_create(self, defaults, **kwargs): - # Allow passing of 'full_name' but replace it with actual database fields - defaults = convert_full_name_to_parts(defaults) - return super().get_or_create(defaults=defaults, **kwargs) - def get_or_create_and_notify(self, defaults=dict(), site=None, **kwargs): defaults.update(is_active=False) user, created = self.get_or_create(defaults=defaults, **kwargs) @@ -63,9 +44,23 @@ class UserManager(BaseUserManager): return user, created -class User(AbstractUser): +class User(AbstractBaseUser, PermissionsMixin): + email = models.EmailField(_('email address'), max_length=255, unique=True) + full_name = models.CharField(verbose_name='Full name', max_length=255, blank=True) + is_staff = models.BooleanField( + verbose_name='staff status', + default=False, + help_text='Designates whether the user can log into this admin site.', + ) + is_active = models.BooleanField( + verbose_name='active', + default=True, + help_text='Designates whether this user should be treated as active. ' + 'Unselect this instead of deleting accounts.', + ) + date_joined = models.DateTimeField(verbose_name='date joined', default=timezone.now) + USERNAME_FIELD = 'email' - email = models.EmailField(_('email address'), unique=True) REQUIRED_FIELDS = [] # Remove the username field which is no longer used @@ -73,5 +68,14 @@ class User(AbstractUser): objects = UserManager() + class Meta: + ordering = ['id'] + def __str__(self): return self.get_full_name() + + def get_full_name(self): + return self.full_name.strip() + + def get_short_name(self): + return self.email diff --git a/opentech/apply/users/templates/wagtailusers/users/create.html b/opentech/apply/users/templates/wagtailusers/users/create.html new file mode 100644 index 000000000..8d546b4a2 --- /dev/null +++ b/opentech/apply/users/templates/wagtailusers/users/create.html @@ -0,0 +1,26 @@ +{% extends "wagtailusers/users/create.html" %} + +{% block fields %} + {% if form.separate_username_field %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.username_field %} + {% endif %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.email %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.full_name %} + + {% comment %} + First/last name hidden input with dummy values because.. Wagtail admin + See opentech.apply.users.forms.CustomUserCreationForm + {% endcomment %} + {{ form.first_name }} + {{ form.last_name }} + + {% if form.password1 %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.password1 %} + {% endif %} + {% if form.password2 %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.password2 %} + {% endif %} + {% if form.is_active %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_active %} + {% endif %} +{% endblock fields %} diff --git a/opentech/apply/users/templates/wagtailusers/users/edit.html b/opentech/apply/users/templates/wagtailusers/users/edit.html new file mode 100644 index 000000000..8eb3ddb49 --- /dev/null +++ b/opentech/apply/users/templates/wagtailusers/users/edit.html @@ -0,0 +1,26 @@ +{% extends "wagtailusers/users/edit.html" %} + +{% block fields %} + {% if form.separate_username_field %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.username_field %} + {% endif %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.email %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.full_name %} + + {% comment %} + First/last name hidden input with dummy values because.. Wagtail admin + See opentech.apply.users.forms.CustomUserEditForm + {% endcomment %} + {{ form.first_name }} + {{ form.last_name }} + + {% if form.password1 %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.password1 %} + {% endif %} + {% if form.password2 %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.password2 %} + {% endif %} + {% if form.is_active %} + {% include "wagtailadmin/shared/field_as_li.html" with field=form.is_active %} + {% endif %} +{% endblock fields %} diff --git a/opentech/settings/base.py b/opentech/settings/base.py index afcbf80bc..3e9b38859 100644 --- a/opentech/settings/base.py +++ b/opentech/settings/base.py @@ -206,6 +206,10 @@ MEDIA_URL = '/media/' AUTH_USER_MODEL = 'users.User' +WAGTAIL_USER_EDIT_FORM = 'opentech.apply.users.forms.CustomUserEditForm' +WAGTAIL_USER_CREATION_FORM = 'opentech.apply.users.forms.CustomUserCreationForm' +WAGTAIL_USER_CUSTOM_FIELDS = ['full_name'] + LOGIN_URL = 'users:login' LOGIN_REDIRECT_URL = 'dashboard:dashboard' -- GitLab