Skip to content
This repository was archived by the owner on Jun 1, 2022. It is now read-only.

Commit 0c3681d

Browse files
committed
Add in signup form and business logic
1 parent cb6da54 commit 0c3681d

File tree

7 files changed

+196
-9
lines changed

7 files changed

+196
-9
lines changed

Diff for: accounts/admin.py

+14-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ def clean_username(self):
1515
data = self.cleaned_data['username']
1616
return data.lower()
1717

18+
class SignupForm(forms.Form):
19+
username = forms.CharField(label='username',
20+
max_length = 60
21+
)
22+
first_name = forms.CharField(label='first name', max_length=50)
23+
last_name = forms.CharField(label='last name', max_length=50)
24+
password1 = forms.CharField(label='password1')
25+
password2 = forms.CharField(label='password2')
26+
27+
def clean_username(self):
28+
data = self.cleaned_data['username']
29+
return data.lower()
30+
1831
class UserCreationForm(forms.ModelForm):
1932
"""A form for creating new users. Includes all the required
2033
fields, plus a repeated password."""
@@ -23,7 +36,7 @@ class UserCreationForm(forms.ModelForm):
2336

2437
class Meta:
2538
model = User
26-
fields = ('username', 'first_name', 'last_name', 'is_author')
39+
fields = ('username', 'first_name', 'last_name', 'is_author', 'password1', 'password2')
2740

2841
def clean_password2(self):
2942
# Check that the two password entries match

Diff for: accounts/static/accounts/accounts.css

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,14 @@
11
.form-signin {
22
width: 100%;
3-
max-width: 330px;
3+
max-width: 30%;
4+
padding: 15px;
5+
margin: auto;
6+
background-color: #9D82EB;
7+
}
8+
9+
.form-signup {
10+
width: 100%;
11+
max-width: 40%;
412
padding: 15px;
513
margin: auto;
614
background-color: #9D82EB;

Diff for: accounts/templates/accounts/signup.html

+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
{% extends "layout.html" %}
2+
{% load static %}
3+
{% load widget_tweaks %}
4+
5+
{% block title %}
6+
Sign up
7+
{% endblock %}
8+
9+
{% block appstatic %}
10+
<link rel="stylesheet" type="text/css" href="{% static 'accounts/accounts.css' %}"/>
11+
{% endblock %}
12+
13+
{% block body %}
14+
<main class="text-center form-signup vertical-center d-flex justify-content-center needs-validation">
15+
<form action="{% url 'signup' %}" method="post">
16+
{% csrf_token %}
17+
<h1 class="mb-4">Please sign up</h1>
18+
19+
{% if form.errors %}
20+
{% for error in form.non_field_errors %}
21+
<div class="alert alert-danger">
22+
<strong>{{ error|escape }}</strong>
23+
</div>
24+
{% endfor %}
25+
{% endif %}
26+
27+
<div class="row g-3 mb-3 justify-content-center">
28+
<div class="col-sm-8">
29+
<div class="form-floating mb-2">
30+
{{ form.username.errors }}
31+
{% render_field form.username class+="form-control" %}
32+
<label for="{{ form.username.id_for_label }}">Username</label>
33+
</div>
34+
</div>
35+
</div>
36+
37+
<div class="row g-3 mb-3">
38+
<div class="col-sm-6">
39+
<div class="form-floating mb-2">
40+
{% if form.first_name.errors %}
41+
{% render_field form.first_name class+="form-control is-invalid" %}
42+
{% else %}
43+
{% render_field form.first_name class+="form-control" %}
44+
{% endif %}
45+
46+
<label for="{{ form.first_name.id_for_label }}">First name</label>
47+
{% for message in form.first_name.errors %}
48+
<p>*{{ message }}</p>
49+
{% endfor %}
50+
</div>
51+
</div>
52+
<div class="col-sm-6">
53+
<div class="form-floating mb-2">
54+
{% if form.last_name.errors %}
55+
{% render_field form.last_name class+="form-control is-invalid" %}
56+
{% else %}
57+
{% render_field form.last_name class+="form-control" %}
58+
{% endif %}
59+
60+
<label for="{{ form.last_name.id_for_label }}">Last name</label>
61+
{% for message in form.last_name.errors %}
62+
<p>*{{ message }}</p>
63+
{% endfor %}
64+
</div>
65+
</div>
66+
</div>
67+
68+
<div class="row g-3 mb-3 justify-content-center">
69+
<div class="col-sm-8">
70+
<div class="form-floating mb-2">
71+
{% if form.password1.errors %}
72+
{% render_field form.password1 class+="form-control is-invalid" type="password" %}
73+
{% else %}
74+
{% render_field form.password1 class+="form-control" type="password" %}
75+
{% endif %}
76+
77+
<label for="{{ form.password1.id_for_label }}">Password</label>
78+
{% for message in form.password1.errors %}
79+
<p>*{{ message }}</p>
80+
{% endfor %}
81+
</div>
82+
</div>
83+
</div>
84+
85+
<div class="row g-3 mb-3 justify-content-center">
86+
<div class="col-sm-8">
87+
<div class="form-floating mb-2">
88+
{% if form.password2.errors %}
89+
{% render_field form.password2 class+="form-control is-invalid" type="password" %}
90+
{% else %}
91+
{% render_field form.password2 class+="form-control" type="password" %}
92+
{% endif %}
93+
94+
<label for="{{ form.password2.id_for_label }}">Password confirmation</label>
95+
{% for message in form.password2.errors %}
96+
<p>*{{ message }}</p>
97+
{% endfor %}
98+
</div>
99+
</div>
100+
</div>
101+
102+
<button class="w-50 btn btn-lg btn-primary mb-5" type="submit">Sign up</button>
103+
104+
<div class="d-flex justify-content-between">
105+
<a class="w-40 btn" onClick="javascript:history.go(-1);">Back</a>
106+
<a class="w-40 btn" href="{% url 'login' %}">Login</a>
107+
</div>
108+
</form>
109+
</main>
110+
{% endblock %}

Diff for: accounts/urls.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33

44
urlpatterns = [
55
path('login', views.signin, name='login'),
6-
path('logoff', views.signout, name='logout')
6+
path('logoff', views.signout, name='logout'),
7+
path('signup', views.signup, name='signup'),
78
]

Diff for: accounts/views.py

+59-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
11
from django.shortcuts import redirect, render
22
from django.urls import reverse
33

4-
from accounts.admin import LoginForm, UserCreationForm
4+
from accounts.admin import LoginForm, SignupForm
55
from django.contrib.auth import authenticate, login, logout
66

7+
import re
8+
9+
from accounts.models import User, UserManager
10+
711
# Create your views here.
812
def signin(request):
9-
1013
if request.method == 'POST':
1114
form = LoginForm(request.POST)
1215

1316
if form.is_valid():
14-
user = form.cleaned_data['username']
15-
passw = form.cleaned_data['password']
17+
user = str(form.cleaned_data['username'])
18+
passw = str(form.cleaned_data['password'])
1619
user = authenticate(username=user, password=passw)
1720
if user is not None:
1821
if user.is_active:
@@ -27,6 +30,58 @@ def signin(request):
2730

2831
return render(request, 'accounts/signin.html', { 'form': form })
2932

33+
def signup(request):
34+
if request.method == 'POST':
35+
form = SignupForm(request.POST)
36+
37+
if form.is_valid():
38+
username = str(form.cleaned_data['username'])
39+
password1 = str(form.cleaned_data['password1'])
40+
password2 = str(form.cleaned_data['password2'])
41+
first_name = str(form.cleaned_data['first_name'])
42+
last_name = str(form.cleaned_data['last_name'])
43+
44+
charactersOnlyPattern = '^[a-zA-Z]+$'
45+
46+
if len(password1) < 8:
47+
form.add_error(field='password1', error='Password is too short')
48+
49+
if password1 != password2:
50+
form.add_error(field='password2', error='Passwords do not match')
51+
52+
if len(first_name) > 50:
53+
form.add_error(field='first_name', error='First name is too long')
54+
55+
if len(last_name) > 50:
56+
form.add_error(field='last_name', error='Last name is too long')
57+
58+
if not re.match(charactersOnlyPattern, first_name):
59+
form.add_error(field='first_name', error='First name cannot only consist of letters')
60+
61+
if not re.match(charactersOnlyPattern, last_name):
62+
form.add_error(field='last_name', error='Last name cannot only consist of letters')
63+
64+
if User.objects.filter(username=username).exists():
65+
form.add_error(field=None, error='Invalid username or password')
66+
return render(request, 'accounts/signup.html', { 'form': form })
67+
68+
usermanager = UserManager()
69+
usermanager.model = User
70+
71+
user = usermanager.create_user(
72+
username=username.lower(),
73+
first_name=first_name,
74+
last_name=last_name,
75+
is_author=False,
76+
password=password1)
77+
78+
login(request=request, user=user)
79+
return redirect(reverse(viewname='home'))
80+
else:
81+
form = SignupForm()
82+
83+
return render(request, 'accounts/signup.html', { 'form': form })
84+
3085
def signout(request):
3186
logout(request)
3287
return redirect(reverse(viewname='home'))

Diff for: common/templates/content.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<li class="nav-item"><a href="{% url 'logout' %}" class="nav-link mr-5">Sign out</a></li>
1919
{% else %}
2020
<li class="nav-item"><a href="{% url 'login' %}" class="nav-link mr-5">Sign in</a></li>
21-
<li class="nav-item"><a href="{% url 'home' %}" class="nav-link">Sign up</a></li>
21+
<li class="nav-item"><a href="{% url 'signup' %}" class="nav-link">Sign up</a></li>
2222
{% endif %}
2323
</ul>
2424
</div>

Diff for: runtime.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
python-3.10.3
1+
python-3.10.4

0 commit comments

Comments
 (0)