Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
0788830
Initial branch commit
auxfuse Oct 16, 2020
34fc3fd
Test commit
auxfuse Oct 16, 2020
7c504ab
.idea/ added to gitignore
auxfuse Oct 16, 2020
d93ccf9
Removed incorrectly pushed Pycharm default .idea folder from repo
auxfuse Oct 16, 2020
365720f
Setup default allauth via settings.py additional allauth settings and…
auxfuse Oct 16, 2020
db72f44
Copied allauth account/socialaccount/base.html template files from Li…
auxfuse Oct 16, 2020
d3d6df3
Default signup Allauth form extended with required fields as per user…
auxfuse Oct 17, 2020
cccd554
Added ommitted spacing around `=` operator in accounts/forms.py file
auxfuse Oct 17, 2020
65d590b
User signup is_active permission set to False using user_signed_up si…
auxfuse Oct 17, 2020
db15842
Fixed merge conflicts
auxfuse Oct 18, 2020
9061b39
Fixed merge conflicts, removed conflict markers and updated gitignore
auxfuse Oct 18, 2020
87cbfb9
Checked form data using request object in forms.py with if..elif..els…
auxfuse Oct 18, 2020
640655d
Set autofocus from username to email field in forms.py for signup tem…
auxfuse Oct 18, 2020
0d7e90c
Up-to-date migrations pushed through
auxfuse Oct 18, 2020
7fb14e9
Updated models/forms/admin.py files of accounts app to suit Profile m…
auxfuse Oct 19, 2020
15f238d
Upstream Master pull to update file directory
auxfuse Oct 19, 2020
15a20ce
Manually added migrations files ommited from latest git pull upstream…
auxfuse Oct 19, 2020
d375e11
accounts app files updated with comments throughout, dependant lists …
auxfuse Oct 19, 2020
1598733
Re-added 0001-inital.py hackathon migration file to solve Operational…
auxfuse Oct 19, 2020
2ac3a44
Merge branch 'master' of https://github.com/Code-Institute-Community/…
auxfuse Oct 19, 2020
f7db244
Refactored accounts .py files to change lists to constants, set user …
auxfuse Oct 20, 2020
0d8968d
Updated accounts/models.py file with CharField null value to be '' as…
auxfuse Oct 20, 2020
8ebdf18
Removed unnecessary comment from accounts/admin.py file and added add…
auxfuse Oct 20, 2020
ada3d30
Default Django allauth authentication templates formatted with IDE fo…
auxfuse Oct 20, 2020
ce4cc3e
Formatted allauth socialAccount templates with IDE formatter includin…
auxfuse Oct 20, 2020
de75a0c
Formatted Django allauth base.html template with default IDE formatter
auxfuse Oct 20, 2020
af7de06
Django allauth email & messages .txt template files formatted manuall…
auxfuse Oct 20, 2020
1fa6f5c
Django allauth socialaccounts messages .txt file templates manually f…
auxfuse Oct 20, 2020
929ec6b
Docstrings added and single line comments removed where necessary to …
auxfuse Oct 20, 2020
62cc59b
.gitignore file updated to include Pycharm default folder of .idea/ a…
auxfuse Oct 20, 2020
2b1ff12
Refactored models.py Profile fields with default='' instead of Null=''
auxfuse Oct 20, 2020
f4d3e52
Migrations made to suit new Profile models.py changes in field attrib…
auxfuse Oct 20, 2020
9366513
Added explicit except catch error in the form of KeyError in the Prof…
auxfuse Oct 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ env.py
*.sqlite3
settings.json
.gitpod.yml
setup.*
setup.*
venv/
.idea/
Empty file added accounts/__init__.py
Empty file.
20 changes: 20 additions & 0 deletions accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.contrib import admin

from .models import Profile


class ProfileAdmin(admin.ModelAdmin):
"""
Profile Model Admin Panel setup.
Returning and displaying the three custom fields from the extended
allauth signup form.
"""
fields = (
'slack_display_name',
'user_type',
'current_lms_module',
)


admin.site.register(Profile, ProfileAdmin)

5 changes: 5 additions & 0 deletions accounts/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class AccountsConfig(AppConfig):
name = 'accounts'
40 changes: 40 additions & 0 deletions accounts/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from django import forms
from allauth.account.forms import SignupForm

from .lists import USER_TYPES_CHOICES, LMS_MODULES_CHOICES


class ExtendedSignupForm(SignupForm):
"""
Extending default Django allauth Signup Form to include fields to capture:
- first name/last name/slack display name/user type/current lms module
"""
first_name = forms.CharField(max_length=20)
last_name = forms.CharField(max_length=20)
slack_display_name = forms.CharField(max_length=25)
user_type = forms.ChoiceField(
choices=USER_TYPES_CHOICES
)
current_lms_module = forms.ChoiceField(
choices=LMS_MODULES_CHOICES
)

def __init__(self, *args, **kwargs):
"""
Setting unique attribute of the class instance and calling the parent
class.
Resetting the form autofocus to 'email' as the first displayed field.
"""
super().__init__(*args, **kwargs)
self.fields['email'].widget.attrs['autofocus'] = True

def custom_signup(self, request, user):
"""
Custom logic to ensure clean data via the form response.
"""
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.slack_display_name = self.cleaned_data["slack_display_name"]
user.user_type = self.cleaned_data["user_type"]
user.current_lms_module = self.cleaned_data["current_lms_module"]

28 changes: 28 additions & 0 deletions accounts/lists.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# User types list passed into dropdown of same name for user selection used
# in models.py & forms.py
USER_TYPES_CHOICES = [
('', 'Select Post Category'),
('participant', 'Participant'),
('staff', 'Staff'),
('admin', 'Admin'),
]

# LMS Modules list passed into dropdown of same name for user selection used
# in modules.py & forms.py
LMS_MODULES_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'),
]

27 changes: 27 additions & 0 deletions accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 3.1.1 on 2020-10-19 10:01

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]

operations = [
migrations.CreateModel(
name='Profile',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slack_display_name', models.CharField(max_length=80, null=True)),
('user_type', models.CharField(choices=[('', 'Select Post Category'), ('participant', 'Participant'), ('staff', 'Staff'), ('admin', 'Admin')], max_length=20, null=True)),
('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)),
('user', models.OneToOneField(default=1, on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL)),
],
),
]
28 changes: 28 additions & 0 deletions accounts/migrations/0002_auto_20201020_2042.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 3.1.1 on 2020-10-20 19:42

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='profile',
name='current_lms_module',
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),
),
migrations.AlterField(
model_name='profile',
name='slack_display_name',
field=models.CharField(default='', max_length=80),
),
migrations.AlterField(
model_name='profile',
name='user_type',
field=models.CharField(choices=[('', 'Select Post Category'), ('participant', 'Participant'), ('staff', 'Staff'), ('admin', 'Admin')], default='', max_length=20),
),
]
Empty file added accounts/migrations/__init__.py
Empty file.
97 changes: 97 additions & 0 deletions accounts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.db import models
from django.conf import settings
from django.db.models.signals import post_delete
from allauth.account.signals import user_signed_up

from .lists import USER_TYPES_CHOICES, LMS_MODULES_CHOICES


class Profile(models.Model):
"""
Define Profile Model with OneToOne relationship to AUTH_USER_MODEL and
custom fields to suit Signup Form Extending in forms.py replicating same
in DB.
Using "related_name" in the OneToOne relationship between the two models
specifies the reverse relationship to the User Model, allowing us to
target the custom fields for injection into the profile.html
template via `{{ user.profile.<<field_name>> }}`.
"""
user = models.OneToOneField(
settings.AUTH_USER_MODEL, default=1,
related_name='profile',
on_delete=models.CASCADE
)
slack_display_name = models.CharField(
max_length=80,
blank=False,
default=''
)
user_type = models.CharField(
max_length=20,
blank=False,
default='',
choices=USER_TYPES_CHOICES
)
current_lms_module = models.CharField(
max_length=35,
blank=False,
default='',
choices=LMS_MODULES_CHOICES
)

def save(self, *args, **kwargs):
# when signup takes place
try:
self.slack_display_name = self.user.slack_display_name
self.user_type = self.user.user_type
self.current_lms_module = self.user.current_lms_module
# when saving via admin panel
except KeyError:
self.slack_display_name = self.user.profile.slack_display_name
self.user_type = self.user.profile.user_type
self.current_lms_module = self.user.profile.current_lms_module

super(Profile, self).save(*args, **kwargs)

def __str__(self):
"""
Return Class object to string via the user email value
"""
return self.user.email


@receiver(user_signed_up)
def user_signed_up(request, user, **kwargs):
"""
Capture server request object in dict from QueryDict, to access form values.

Iterate over user_type field value to check for type and set permissions
based on user story and save user to User and Profile Models.
"""
form = dict(request.POST)

if form['user_type'][0] == 'participant':
user.is_active = True
elif form['user_type'][0] == 'staff':
user.is_active = False
user.is_staff = True
else:
user.is_active = False
user.is_staff = True
user.is_superuser = True
user.save()

# Save linked instance of user object to profile model
Profile.objects.create(user=user)


@receiver(post_delete, sender=Profile)
def post_delete_user(sender, instance, *args, **kwargs):
"""
admin - delete user at same time as profile deletion
"""
if instance:
instance.user.delete()

1 change: 1 addition & 0 deletions accounts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from django.test import TestCase
1 change: 1 addition & 0 deletions accounts/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from django.shortcuts import render
2 changes: 1 addition & 1 deletion hackathon/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ class Migration(migrations.Migration):
('organiser', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hackathon_organiser', to=settings.AUTH_USER_MODEL)),
],
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0002_auto_20201015_1936.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ class Migration(migrations.Migration):
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackawardcategory_created_by', to=settings.AUTH_USER_MODEL)),
],
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0003_auto_20201015_2020.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ class Migration(migrations.Migration):
('mentor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='hackproject_mentor', to=settings.AUTH_USER_MODEL)),
],
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0004_auto_20201015_2224.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ class Migration(migrations.Migration):
('score', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='hackathon.hackprojectscorecategory')),
],
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0005_auto_20201016_1951.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ class Migration(migrations.Migration):
name='created',
field=models.DateTimeField(auto_now_add=True),
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0006_auto_20201016_2050.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ class Migration(migrations.Migration):
old_name='hackprojectscorecategory',
new_name='hack_project_score_category',
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0007_auto_20201017_1148.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ class Migration(migrations.Migration):
name='created_by',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='hackteams', to=settings.AUTH_USER_MODEL),
),
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ class Migration(migrations.Migration):
name='highest_score',
field=models.IntegerField(default=10),
),
]
]
2 changes: 1 addition & 1 deletion hackathon/migrations/0009_auto_20201018_1829.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ class Migration(migrations.Migration):
name='min_score',
field=models.IntegerField(default=1),
),
]
]
13 changes: 13 additions & 0 deletions main/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"allauth.account",
"allauth.socialaccount",
"home",
'accounts',
"profiles",
"crispy_forms",
# M05 App "Hackathon" added
Expand Down Expand Up @@ -81,6 +82,18 @@

SITE_ID = 1

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

ACCOUNT_FORMS = {'signup': 'accounts.forms.ExtendedSignupForm'}
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_SIGNUP_EMAIL_ENTER_TWICE = True
ACCOUNT_USERNAME_MIN_LENGTH = 4
LOGIN_URL = '/accounts/login/'
LOGIN_REDIRECT_URL = '/'

WSGI_APPLICATION = "main.wsgi.application"


Expand Down
10 changes: 10 additions & 0 deletions templates/allauth/account/account_inactive.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{% extends "account/base.html" %}

{% load i18n %}

{% block head_title %}{% trans "Account Inactive" %}{% endblock %}

{% block content %}
<h1>{% trans "Account Inactive" %}</h1>
<p>{% trans "This account is inactive." %}</p>
{% endblock %}
1 change: 1 addition & 0 deletions templates/allauth/account/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% extends "base.html" %}
Loading