diff --git a/core/forms.py b/core/forms.py index ae0e537d..1ac601e2 100644 --- a/core/forms.py +++ b/core/forms.py @@ -1,4 +1,8 @@ -from django.contrib.auth.forms import UserCreationForm +from django.contrib.auth.forms import UserCreationForm, AuthenticationForm +from django import forms +from django.contrib.auth import logout, login, authenticate +import logging + from .models import User class RegisteringForm(UserCreationForm): @@ -6,4 +10,36 @@ class RegisteringForm(UserCreationForm): required_css_class = 'required' class Meta: model = User - fields = ('username', 'email',) + fields = ('first_name', 'last_name', 'email') + + def save(self, commit=True): + user = super(RegisteringForm, self).save(commit=False) + user.set_password(self.cleaned_data["password1"]) + user.generate_username() + if commit: + user.save() + return user + +class LoginForm(AuthenticationForm): + def login(self): + u = authenticate(username=self.request.POST['username'], + password=self.request.POST['password']) + if u is not None: + if u.is_active: + login(self.request, u) + logging.debug("Logging in "+u) + else: + raise forms.ValidationError( + self.error_messages['invalid_login'], + code='inactive', + params={'username': self.username_field.verbose_name}, + ) + else: + logging.debug("Login failed") + raise forms.ValidationError( + self.error_messages['invalid_login'], + code='invalid_login', + params={'username': self.username_field.verbose_name}, + ) + + diff --git a/core/migrations/0001_initial.py b/core/migrations/0001_initial.py index b46ffff2..f024ebcb 100644 --- a/core/migrations/0001_initial.py +++ b/core/migrations/0001_initial.py @@ -2,9 +2,9 @@ from __future__ import unicode_literals from django.db import migrations, models +import django.utils.timezone import django.core.validators import django.contrib.auth.models -import django.utils.timezone class Migration(migrations.Migration): @@ -17,25 +17,25 @@ class Migration(migrations.Migration): migrations.CreateModel( name='User', fields=[ - ('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True, serialize=False)), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, verbose_name='last login', null=True)), - ('is_superuser', models.BooleanField(verbose_name='superuser status', default=False, help_text='Designates that this user has all permissions without explicitly assigning them.')), - ('username', models.CharField(unique=True, validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.', 'invalid')], verbose_name='username', max_length=30, error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.')), - ('first_name', models.CharField(max_length=30, blank=True, verbose_name='first name')), - ('last_name', models.CharField(max_length=30, blank=True, verbose_name='last name')), - ('email', models.EmailField(max_length=254, blank=True, verbose_name='email address')), - ('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=django.utils.timezone.now)), - ('nick_name', models.CharField(max_length=30)), - ('groups', models.ManyToManyField(related_query_name='user', related_name='user_set', verbose_name='groups', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.')), - ('user_permissions', models.ManyToManyField(related_query_name='user', related_name='user_set', verbose_name='user permissions', to='auth.Permission', blank=True, help_text='Specific permissions for this user.')), + ('id', models.AutoField(primary_key=True, auto_created=True, verbose_name='ID', serialize=False)), + ('password', models.CharField(verbose_name='password', max_length=128)), + ('last_login', models.DateTimeField(null=True, blank=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(validators=[django.core.validators.RegexValidator('^[\\w.@+-]+$', 'Enter a valid username. This value may contain only letters, numbers and @/./+/-/_ characters.')], help_text='Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.', error_messages={'unique': 'A user with that username already exists.'}, verbose_name='username', unique=True, max_length=254)), + ('first_name', models.CharField(verbose_name='first name', max_length=30)), + ('last_name', models.CharField(verbose_name='last name', max_length=30)), + ('email', models.EmailField(verbose_name='email address', unique=True, max_length=254)), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('date_of_birth', models.DateTimeField(verbose_name='date of birth')), + ('nick_name', models.CharField(blank=True, max_length=30)), + ('groups', models.ManyToManyField(related_query_name='user', help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', blank=True, to='auth.Group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(related_query_name='user', help_text='Specific permissions for this user.', related_name='user_set', blank=True, to='auth.Permission', verbose_name='user permissions')), ], options={ - 'verbose_name': 'user', 'verbose_name_plural': 'users', - 'abstract': False, + 'verbose_name': 'user', }, managers=[ ('objects', django.contrib.auth.models.UserManager()), diff --git a/core/models.py b/core/models.py index 3b0de951..13f8005a 100644 --- a/core/models.py +++ b/core/models.py @@ -1,15 +1,100 @@ from django.db import models -from django.contrib.auth.models import AbstractUser +from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager +from django.utils.translation import ugettext_lazy as _ +from django.core import validators +from django.utils import timezone -import logging +class User(AbstractBaseUser, PermissionsMixin): + """ + Defines the base user class, useable in every app -logging.basicConfig(level=logging.DEBUG) + This is almost the same as the auth module AbstractUser since it inherits from it, + but some fields are required, and the username is generated automatically with the + name of the user (see generate_username()). -class User(AbstractUser): - nick_name = models.CharField(max_length=30) + Added field: nick_name + Required fields: email, first_name, last_name, date_of_birth + """ + username = models.CharField( + _('username'), + max_length=254, + unique=True, + help_text=_('Required. 254 characters or fewer. Letters, digits and @/./+/-/_ only.'), + validators=[ + validators.RegexValidator( + r'^[\w.@+-]+$', + _('Enter a valid username. This value may contain only ' + 'letters, numbers ' 'and @/./+/-/_ characters.') + ), + ], + error_messages={ + 'unique': _("A user with that username already exists."), + }, + ) + first_name = models.CharField(_('first name'), max_length=30) + last_name = models.CharField(_('last name'), max_length=30) + email = models.EmailField(_('email address'), unique=True) + date_of_birth = models.DateTimeField(_('date of birth'), default="1970-01-01") + nick_name = models.CharField(max_length=30, blank=True) + is_staff = models.BooleanField( + _('staff status'), + default=False, + help_text=_('Designates whether the user can log into this admin site.'), + ) + is_active = models.BooleanField( + _('active'), + default=True, + help_text=_( + 'Designates whether this user should be treated as active. ' + 'Unselect this instead of deleting accounts.' + ), + ) + date_joined = models.DateTimeField(_('date joined'), default=timezone.now) + + objects = UserManager() + + USERNAME_FIELD = 'username' + REQUIRED_FIELDS = ['email', 'first_name', 'last_name'] + + class Meta: + verbose_name = _('user') + verbose_name_plural = _('users') def __str__(self): - return self.get_username() + return self.username + + def get_full_name(self): + """ + Returns the first_name plus the last_name, with a space in between. + """ + full_name = '%s %s' % (self.first_name, self.last_name) + return full_name.strip() + + def get_short_name(self): + "Returns the short name for the user." + return self.first_name + + def email_user(self, subject, message, from_email=None, **kwargs): + """ + Sends an email to this User. + """ + send_mail(subject, message, from_email, [self.email], **kwargs) + + def generate_username(self): + """ + Generates a unique username based on the first and last names. + For example: Guy Carlier gives gcarlier, and gcarlier1 if the first one exists + Returns the generated username + """ + user_name = str(self.first_name[0]+self.last_name).lower() + un_set = [u.username for u in User.objects.all()] + if user_name in un_set: + i = 1 + while user_name+str(i) in un_set: + i += 1 + user_name += str(i) + self.username = user_name + return user_name class Page: pass diff --git a/core/templates/core/base.html b/core/templates/core/base.html new file mode 100644 index 00000000..e9573f29 --- /dev/null +++ b/core/templates/core/base.html @@ -0,0 +1,30 @@ + + +
+ +