Skip to content

Commit c3d01ca

Browse files
authored
#M00. As a User, I would like to register an account. - Auxfuse (#83)
1 parent f075566 commit c3d01ca

67 files changed

Lines changed: 893 additions & 10 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ env.py
99
*.sqlite3
1010
settings.json
1111
.gitpod.yml
12-
setup.*
12+
setup.*
13+
venv/
14+
.idea/

accounts/__init__.py

Whitespace-only changes.

accounts/admin.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
from django.contrib import admin
2+
3+
from .models import Profile
4+
5+
6+
class ProfileAdmin(admin.ModelAdmin):
7+
"""
8+
Profile Model Admin Panel setup.
9+
Returning and displaying the three custom fields from the extended
10+
allauth signup form.
11+
"""
12+
fields = (
13+
'slack_display_name',
14+
'user_type',
15+
'current_lms_module',
16+
)
17+
18+
19+
admin.site.register(Profile, ProfileAdmin)
20+

accounts/apps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class AccountsConfig(AppConfig):
5+
name = 'accounts'

accounts/forms.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
from django import forms
2+
from allauth.account.forms import SignupForm
3+
4+
from .lists import USER_TYPES_CHOICES, LMS_MODULES_CHOICES
5+
6+
7+
class ExtendedSignupForm(SignupForm):
8+
"""
9+
Extending default Django allauth Signup Form to include fields to capture:
10+
- first name/last name/slack display name/user type/current lms module
11+
"""
12+
first_name = forms.CharField(max_length=20)
13+
last_name = forms.CharField(max_length=20)
14+
slack_display_name = forms.CharField(max_length=25)
15+
user_type = forms.ChoiceField(
16+
choices=USER_TYPES_CHOICES
17+
)
18+
current_lms_module = forms.ChoiceField(
19+
choices=LMS_MODULES_CHOICES
20+
)
21+
22+
def __init__(self, *args, **kwargs):
23+
"""
24+
Setting unique attribute of the class instance and calling the parent
25+
class.
26+
Resetting the form autofocus to 'email' as the first displayed field.
27+
"""
28+
super().__init__(*args, **kwargs)
29+
self.fields['email'].widget.attrs['autofocus'] = True
30+
31+
def custom_signup(self, request, user):
32+
"""
33+
Custom logic to ensure clean data via the form response.
34+
"""
35+
user.first_name = self.cleaned_data["first_name"]
36+
user.last_name = self.cleaned_data["last_name"]
37+
user.slack_display_name = self.cleaned_data["slack_display_name"]
38+
user.user_type = self.cleaned_data["user_type"]
39+
user.current_lms_module = self.cleaned_data["current_lms_module"]
40+

accounts/lists.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# User types list passed into dropdown of same name for user selection used
2+
# in models.py & forms.py
3+
USER_TYPES_CHOICES = [
4+
('', 'Select Post Category'),
5+
('participant', 'Participant'),
6+
('staff', 'Staff'),
7+
('admin', 'Admin'),
8+
]
9+
10+
# LMS Modules list passed into dropdown of same name for user selection used
11+
# in modules.py & forms.py
12+
LMS_MODULES_CHOICES = [
13+
('', 'Select Learning Stage'),
14+
('programme_preliminaries', 'Programme Preliminaries'),
15+
('programming_paradigms', 'Programming Paradigms'),
16+
('html_fundamentals', 'HTML Fundamentals'),
17+
('css_fundamentals', 'CSS Fundamentals'),
18+
('user_centric_frontend_development', 'User Centric Frontend Development'),
19+
('javascript_fundamentals', 'Javascript Fundamentals'),
20+
('interactive_frontend_development', 'Interactive Frontend Development'),
21+
('python_fundamentals', 'Python Fundamentals'),
22+
('practical_python', 'Practical Python'),
23+
('data_centric_development', 'Data Centric Development'),
24+
('full_stack_frameworks with django', 'Full Stack Frameworks with Django'),
25+
('alumni', 'Alumni'),
26+
('staff', 'Staff'),
27+
]
28+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Generated by Django 3.1.1 on 2020-10-19 10:01
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
initial = True
11+
12+
dependencies = [
13+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
14+
]
15+
16+
operations = [
17+
migrations.CreateModel(
18+
name='Profile',
19+
fields=[
20+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
21+
('slack_display_name', models.CharField(max_length=80, null=True)),
22+
('user_type', models.CharField(choices=[('', 'Select Post Category'), ('participant', 'Participant'), ('staff', 'Staff'), ('admin', 'Admin')], max_length=20, null=True)),
23+
('current_lms_module', models.CharField(choices=[('', 'Select Learning Stage'), ('programme preliminaries', 'Programme Preliminaries'), ('programming paradigms', 'Programming Paradigms'), ('html fundamentals', 'HTML Fundamentals'), ('css fundamentals', 'CSS Fundamentals'), ('user centric frontend development', 'User Centric Frontend Development'), ('javascript fundamentals', 'Javascript Fundamentals'), ('interactive frontend development', 'Interactive Frontend Development'), ('python fundamentals', 'Python Fundamentals'), ('practical python', 'Practical Python'), ('data centric development', 'Data Centric Development'), ('full stack frameworks with django', 'Full Stack Frameworks with Django'), ('alumni', 'Alumni'), ('staff', 'Staff')], max_length=35, null=True)),
24+
('user', models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
25+
],
26+
),
27+
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 3.1.1 on 2020-10-20 19:42
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('accounts', '0001_initial'),
10+
]
11+
12+
operations = [
13+
migrations.AlterField(
14+
model_name='profile',
15+
name='current_lms_module',
16+
field=models.CharField(choices=[('', 'Select Learning Stage'), ('programme_preliminaries', 'Programme Preliminaries'), ('programming_paradigms', 'Programming Paradigms'), ('html_fundamentals', 'HTML Fundamentals'), ('css_fundamentals', 'CSS Fundamentals'), ('user_centric_frontend_development', 'User Centric Frontend Development'), ('javascript_fundamentals', 'Javascript Fundamentals'), ('interactive_frontend_development', 'Interactive Frontend Development'), ('python_fundamentals', 'Python Fundamentals'), ('practical_python', 'Practical Python'), ('data_centric_development', 'Data Centric Development'), ('full_stack_frameworks with django', 'Full Stack Frameworks with Django'), ('alumni', 'Alumni'), ('staff', 'Staff')], default='', max_length=35),
17+
),
18+
migrations.AlterField(
19+
model_name='profile',
20+
name='slack_display_name',
21+
field=models.CharField(default='', max_length=80),
22+
),
23+
migrations.AlterField(
24+
model_name='profile',
25+
name='user_type',
26+
field=models.CharField(choices=[('', 'Select Post Category'), ('participant', 'Participant'), ('staff', 'Staff'), ('admin', 'Admin')], default='', max_length=20),
27+
),
28+
]

accounts/migrations/__init__.py

Whitespace-only changes.

accounts/models.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
from django.dispatch import receiver
2+
from django.contrib.auth.models import User
3+
from django.db import models
4+
from django.conf import settings
5+
from django.db.models.signals import post_delete
6+
from allauth.account.signals import user_signed_up
7+
8+
from .lists import USER_TYPES_CHOICES, LMS_MODULES_CHOICES
9+
10+
11+
class Profile(models.Model):
12+
"""
13+
Define Profile Model with OneToOne relationship to AUTH_USER_MODEL and
14+
custom fields to suit Signup Form Extending in forms.py replicating same
15+
in DB.
16+
Using "related_name" in the OneToOne relationship between the two models
17+
specifies the reverse relationship to the User Model, allowing us to
18+
target the custom fields for injection into the profile.html
19+
template via `{{ user.profile.<<field_name>> }}`.
20+
"""
21+
user = models.OneToOneField(
22+
settings.AUTH_USER_MODEL, default=1,
23+
related_name='profile',
24+
on_delete=models.CASCADE
25+
)
26+
slack_display_name = models.CharField(
27+
max_length=80,
28+
blank=False,
29+
default=''
30+
)
31+
user_type = models.CharField(
32+
max_length=20,
33+
blank=False,
34+
default='',
35+
choices=USER_TYPES_CHOICES
36+
)
37+
current_lms_module = models.CharField(
38+
max_length=35,
39+
blank=False,
40+
default='',
41+
choices=LMS_MODULES_CHOICES
42+
)
43+
44+
def save(self, *args, **kwargs):
45+
# when signup takes place
46+
try:
47+
self.slack_display_name = self.user.slack_display_name
48+
self.user_type = self.user.user_type
49+
self.current_lms_module = self.user.current_lms_module
50+
# when saving via admin panel
51+
except KeyError:
52+
self.slack_display_name = self.user.profile.slack_display_name
53+
self.user_type = self.user.profile.user_type
54+
self.current_lms_module = self.user.profile.current_lms_module
55+
56+
super(Profile, self).save(*args, **kwargs)
57+
58+
def __str__(self):
59+
"""
60+
Return Class object to string via the user email value
61+
"""
62+
return self.user.email
63+
64+
65+
@receiver(user_signed_up)
66+
def user_signed_up(request, user, **kwargs):
67+
"""
68+
Capture server request object in dict from QueryDict, to access form values.
69+
70+
Iterate over user_type field value to check for type and set permissions
71+
based on user story and save user to User and Profile Models.
72+
"""
73+
form = dict(request.POST)
74+
75+
if form['user_type'][0] == 'participant':
76+
user.is_active = True
77+
elif form['user_type'][0] == 'staff':
78+
user.is_active = False
79+
user.is_staff = True
80+
else:
81+
user.is_active = False
82+
user.is_staff = True
83+
user.is_superuser = True
84+
user.save()
85+
86+
# Save linked instance of user object to profile model
87+
Profile.objects.create(user=user)
88+
89+
90+
@receiver(post_delete, sender=Profile)
91+
def post_delete_user(sender, instance, *args, **kwargs):
92+
"""
93+
admin - delete user at same time as profile deletion
94+
"""
95+
if instance:
96+
instance.user.delete()
97+

0 commit comments

Comments
 (0)