mirror of
https://github.com/Balshgit/different
synced 2025-09-11 02:50:41 +03:00
accounts authorization app
This commit is contained in:
parent
d518d1f8da
commit
3f14070560
0
django_accounts_app/__init__.py
Normal file
0
django_accounts_app/__init__.py
Normal file
48
django_accounts_app/admin.py
Normal file
48
django_accounts_app/admin.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
from server.apps.accounts.models import CustomUser, CustomGroup
|
||||||
|
from django.contrib import admin
|
||||||
|
from django.contrib.auth.admin import UserAdmin, GroupAdmin, Group
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(CustomUser)
|
||||||
|
class CustomUserAdmin(UserAdmin):
|
||||||
|
|
||||||
|
model = CustomUser
|
||||||
|
|
||||||
|
list_display = ('username', 'email', 'first_name', 'last_name', 'mobile', 'verification_code',
|
||||||
|
'is_superuser', 'is_staff', 'is_active', )
|
||||||
|
|
||||||
|
list_filter = ('username', 'first_name', 'last_name', 'user_created', 'is_superuser', 'is_staff', 'is_active', )
|
||||||
|
|
||||||
|
ordering = ('user_created', 'username', 'first_name', 'is_superuser', 'is_staff', 'is_active', )
|
||||||
|
|
||||||
|
fieldsets = (
|
||||||
|
(None, {'fields': ('username', 'password')}),
|
||||||
|
('Main fields', {'fields': ('first_name', 'last_name', 'verification_code', 'user_created', )}
|
||||||
|
),
|
||||||
|
('Contacts', {'fields': ('email', 'mobile', )}
|
||||||
|
),
|
||||||
|
('Permissions', {'fields': ('groups', 'user_permissions', 'is_superuser', 'is_staff', 'is_active')}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
add_fieldsets = (
|
||||||
|
('Main fields', {
|
||||||
|
'classes': ('wide', ),
|
||||||
|
'fields': ('username', 'email', 'mobile', 'password1', 'password2', 'verification_code', )
|
||||||
|
}),
|
||||||
|
('Permissions', {
|
||||||
|
'classes': ('wide', ),
|
||||||
|
'fields': ('groups', 'user_permissions', 'is_superuser', 'is_staff', 'is_active')
|
||||||
|
})
|
||||||
|
)
|
||||||
|
readonly_fields = ('user_created', )
|
||||||
|
|
||||||
|
search_fields = ('username', 'first_name', 'last_name', 'mobile', 'email')
|
||||||
|
filter_horizontal = ('groups', 'user_permissions',)
|
||||||
|
|
||||||
|
|
||||||
|
admin.site.unregister(Group)
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(CustomGroup)
|
||||||
|
class CustomGroupAdmin(GroupAdmin):
|
||||||
|
...
|
6
django_accounts_app/apps.py
Normal file
6
django_accounts_app/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUserConfig(AppConfig):
|
||||||
|
name = 'server.apps.accounts'
|
||||||
|
verbose_name = 'Admin User manager'
|
18
django_accounts_app/forms.py
Normal file
18
django_accounts_app/forms.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
from django import forms
|
||||||
|
from django.contrib.auth.forms import UserCreationForm
|
||||||
|
|
||||||
|
from server.apps.accounts.models import CustomUser
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUserCreationForm(UserCreationForm):
|
||||||
|
# username = forms.CharField(label='Логин', widget=forms.TextInput(attrs={'class': 'form-input'}))
|
||||||
|
# email = forms.EmailField(label='Email', widget=forms.EmailInput(attrs={'class': 'form-input'}))
|
||||||
|
# password1 = forms.CharField(label='Пароль', widget=forms.PasswordInput(attrs={'class': 'form-input'}))
|
||||||
|
# password2 = forms.CharField(label='Повтор пароля',
|
||||||
|
# widget=forms.PasswordInput(attrs={'class': 'form-input'}))
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = CustomUser
|
||||||
|
fields = ('username', 'first_name', 'last_name', 'email', 'mobile', 'password1', 'password2')
|
||||||
|
|
||||||
|
|
27
django_accounts_app/managers.py
Normal file
27
django_accounts_app/managers.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
from django.contrib.auth.base_user import BaseUserManager
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUserManager(BaseUserManager):
|
||||||
|
|
||||||
|
def create_user(self, username, password, **extra_fields):
|
||||||
|
|
||||||
|
if not username:
|
||||||
|
raise ValueError(_('The username must be set'))
|
||||||
|
user = self.model(username=username, **extra_fields)
|
||||||
|
user.set_password(password)
|
||||||
|
user.save()
|
||||||
|
return user
|
||||||
|
|
||||||
|
def create_superuser(self, username, password, **extra_fields):
|
||||||
|
"""
|
||||||
|
Create and save a SuperUser with the given email and password.
|
||||||
|
"""
|
||||||
|
extra_fields.setdefault('is_staff', True)
|
||||||
|
extra_fields.setdefault('is_superuser', True)
|
||||||
|
extra_fields.setdefault('is_active', True)
|
||||||
|
if extra_fields.get('is_staff') is not True:
|
||||||
|
raise ValueError(_('Superuser must have is_staff=True.'))
|
||||||
|
if extra_fields.get('is_superuser') is not True:
|
||||||
|
raise ValueError(_('Superuser must have is_superuser=True.'))
|
||||||
|
return self.create_user(username, password, **extra_fields)
|
0
django_accounts_app/migrations/__init__.py
Normal file
0
django_accounts_app/migrations/__init__.py
Normal file
59
django_accounts_app/migrations/create_accounts_models.py
Normal file
59
django_accounts_app/migrations/create_accounts_models.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Generated by Django 3.2.8 on 2021-10-24 11:03
|
||||||
|
|
||||||
|
import django.contrib.auth.models
|
||||||
|
import django.contrib.auth.validators
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0012_alter_user_first_name_max_length'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CustomGroup',
|
||||||
|
fields=[
|
||||||
|
('group_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='auth.group')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'Permissions group',
|
||||||
|
'verbose_name_plural': 'Permissions groups',
|
||||||
|
},
|
||||||
|
bases=('auth.group',),
|
||||||
|
managers=[
|
||||||
|
('objects', django.contrib.auth.models.GroupManager()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CustomUser',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('password', models.CharField(max_length=128, verbose_name='password')),
|
||||||
|
('last_login', models.DateTimeField(blank=True, null=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(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
|
||||||
|
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
|
||||||
|
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
|
||||||
|
('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')),
|
||||||
|
('mobile', models.CharField(blank=True, help_text='Users mobile phone', max_length=15, null=True, unique=True)),
|
||||||
|
('verification_code', models.CharField(blank=True, help_text='Verification code for bot account', max_length=10, null=True, unique=True)),
|
||||||
|
('user_created', models.DateField(auto_now_add=True, help_text='Date when user has been created', verbose_name='User created')),
|
||||||
|
('email', models.EmailField(help_text='User email', max_length=30, null=True, unique=True)),
|
||||||
|
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
|
||||||
|
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'user',
|
||||||
|
'verbose_name_plural': 'users',
|
||||||
|
'abstract': False,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
26
django_accounts_app/models.py
Normal file
26
django_accounts_app/models.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import AbstractUser, Group
|
||||||
|
from .managers import CustomUserManager
|
||||||
|
|
||||||
|
|
||||||
|
class CustomUser(AbstractUser):
|
||||||
|
|
||||||
|
mobile = models.CharField(max_length=15, null=True, blank=True, unique=True,
|
||||||
|
help_text='Users mobile phone')
|
||||||
|
verification_code = models.CharField(max_length=10, unique=True, null=True, blank=True,
|
||||||
|
help_text='Verification code for bot account')
|
||||||
|
user_created = models.DateField(editable=False, auto_now_add=True, verbose_name='User created',
|
||||||
|
help_text='Date when user has been created')
|
||||||
|
email = models.EmailField(max_length=30, unique=True, blank=False, null=True, help_text='User email')
|
||||||
|
USERNAME_FIELD = 'username'
|
||||||
|
REQUIRED_FIELDS = ['email']
|
||||||
|
objects = CustomUserManager()
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.username
|
||||||
|
|
||||||
|
|
||||||
|
class CustomGroup(Group):
|
||||||
|
class Meta:
|
||||||
|
verbose_name = 'Permissions group'
|
||||||
|
verbose_name_plural = 'Permissions groups'
|
16
django_accounts_app/tasks.py
Normal file
16
django_accounts_app/tasks.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
from celery import shared_task
|
||||||
|
from django.core.mail import send_mail
|
||||||
|
from django.conf import settings
|
||||||
|
from django.template.loader import render_to_string
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task
|
||||||
|
def mail_send(to_email: str, subject: str, text_content: str = '', **kwargs) -> None:
|
||||||
|
|
||||||
|
username = kwargs.get('username')
|
||||||
|
from_email = settings.DEFAULT_FROM_EMAIL
|
||||||
|
|
||||||
|
msg_html = render_to_string('registration/message.html',
|
||||||
|
{'username': username})
|
||||||
|
|
||||||
|
send_mail(subject, text_content, from_email, [to_email], html_message=msg_html, fail_silently=False)
|
3
django_accounts_app/templates/base.html
Normal file
3
django_accounts_app/templates/base.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{% block content %}
|
||||||
|
|
||||||
|
{% endblock %}
|
120
django_accounts_app/templates/registration/login.html
Normal file
120
django_accounts_app/templates/registration/login.html
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,700">
|
||||||
|
<title>Bootstrap Simple Login Form with Blue Background</title>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
color: #fff;
|
||||||
|
background: #3598dc;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
.form-control {
|
||||||
|
height: 41px;
|
||||||
|
background: #f2f2f2;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.form-control:focus {
|
||||||
|
background: #e2e2e2;
|
||||||
|
}
|
||||||
|
.form-control, .btn {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.signup-form {
|
||||||
|
width: 400px;
|
||||||
|
margin: 30px auto;
|
||||||
|
}
|
||||||
|
.signup-form form {
|
||||||
|
color: #999;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.signup-form h2 {
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.signup-form hr {
|
||||||
|
margin: 0 -30px 20px;
|
||||||
|
}
|
||||||
|
.signup-form .form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.signup-form input[type="checkbox"] {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
.signup-form .row div:first-child {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
.signup-form .row div:last-child {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.signup-form .btn {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #3598dc;
|
||||||
|
border: none;
|
||||||
|
min-width: 140px;
|
||||||
|
}
|
||||||
|
.signup-form .btn:hover, .signup-form .btn:focus {
|
||||||
|
background: #2389cd !important;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.signup-form a {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.signup-form a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.signup-form form a {
|
||||||
|
color: #3598dc;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.signup-form form a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.signup-form .hint-text {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="signup-form">
|
||||||
|
<form method="post">
|
||||||
|
<h2>Login</h2>
|
||||||
|
<p>Please fill in this form to Log in</p>
|
||||||
|
<hr>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" name="username" placeholder="Username" required="required">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" class="form-control" name="password" placeholder="Password" required="required">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-primary btn-lg">Login</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{% if form.non_field_errors %}
|
||||||
|
{% for error in form.non_field_errors %}
|
||||||
|
<li>{{ error }}</li>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="hint-text">Don't have an account? <a href="{% url 'accounts:registration' %}">Register here</a></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
6
django_accounts_app/templates/registration/message.html
Normal file
6
django_accounts_app/templates/registration/message.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<p style="color: green">Добро пожаловать, {{ username }}!</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
@ -0,0 +1,8 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>Password Changed successfully</h2>
|
||||||
|
<a href="{% url 'accounts:dashboard' %}">Back to dashboard</a>
|
||||||
|
|
||||||
|
{% endblock %}
|
@ -0,0 +1,13 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<h2>Password Change</h2>
|
||||||
|
<form method='POST'>
|
||||||
|
{% csrf_token %}
|
||||||
|
{{form.as_p}}
|
||||||
|
<input type="submit" value="Change">
|
||||||
|
</form>
|
||||||
|
<a href="{% url 'accounts:dashboard' %}">Back to dashboard</a>
|
||||||
|
|
||||||
|
{% endblock %}
|
17
django_accounts_app/templates/users/dashboard.html
Normal file
17
django_accounts_app/templates/users/dashboard.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
Hello {{ user.username|default:'guest' }}!
|
||||||
|
|
||||||
|
<div>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a href="{% url 'accounts:logout' %}">Logout</a>
|
||||||
|
<a href="{% url 'accounts:password_change' %}">Change Password</a>
|
||||||
|
<a href="{% url 'accounts:portfolio' %}">Go to Profile page</a>
|
||||||
|
{% else %}
|
||||||
|
<a href="{% url 'accounts:login' %}">Login</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock %}
|
154
django_accounts_app/templates/users/register.html
Normal file
154
django_accounts_app/templates/users/register.html
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,700">
|
||||||
|
<title>Bootstrap Simple Login Form with Blue Background</title>
|
||||||
|
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
|
||||||
|
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||||
|
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js"></script>
|
||||||
|
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
color: #fff;
|
||||||
|
background: #3598dc;
|
||||||
|
font-family: 'Roboto', sans-serif;
|
||||||
|
}
|
||||||
|
.form-control {
|
||||||
|
height: 41px;
|
||||||
|
background: #f2f2f2;
|
||||||
|
box-shadow: none !important;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
.form-control:focus {
|
||||||
|
background: #e2e2e2;
|
||||||
|
}
|
||||||
|
.form-control, .btn {
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
.signup-form {
|
||||||
|
width: 400px;
|
||||||
|
margin: 30px auto;
|
||||||
|
}
|
||||||
|
.signup-form form {
|
||||||
|
color: #999;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin-bottom: 15px;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.signup-form h2 {
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
.signup-form hr {
|
||||||
|
margin: 0 -30px 20px;
|
||||||
|
}
|
||||||
|
.signup-form .form-group {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.signup-form input[type="checkbox"] {
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
.signup-form .row div:first-child {
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
.signup-form .row div:last-child {
|
||||||
|
padding-left: 10px;
|
||||||
|
}
|
||||||
|
.signup-form .btn {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #3598dc;
|
||||||
|
border: none;
|
||||||
|
min-width: 140px;
|
||||||
|
}
|
||||||
|
.signup-form .btn:hover, .signup-form .btn:focus {
|
||||||
|
background: #2389cd !important;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
.signup-form a {
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.signup-form a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.signup-form form a {
|
||||||
|
color: #3598dc;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
.signup-form form a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.signup-form .hint-text {
|
||||||
|
padding-bottom: 15px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="signup-form">
|
||||||
|
<form method="post">
|
||||||
|
<h2>Sign Up</h2>
|
||||||
|
<p>Please fill in this form to create an account!</p>
|
||||||
|
<hr>
|
||||||
|
{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
{% if form.username.value %}
|
||||||
|
<input type="text" class="form-control" name="username" value="{{ form.username.value }}">
|
||||||
|
{% else %}
|
||||||
|
<input type="text" class="form-control" name="username" placeholder="Username" required="required">
|
||||||
|
{% endif %}
|
||||||
|
<div class="form-group">{{ form.username.errors }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="row">
|
||||||
|
{% if form.first_name.value %}
|
||||||
|
<div class="col"><input type="text" class="form-control" name="first_name" value="{{ form.first_name.value }}"></div>
|
||||||
|
{% else %}
|
||||||
|
<div class="col"><input type="text" class="form-control" name="first_name" placeholder="First Name" required="required"></div>
|
||||||
|
{% endif %}
|
||||||
|
{% if form.last_name.value %}
|
||||||
|
<div class="col"><input type="text" class="form-control" name="last_name" value="{{ form.last_name.value }}"></div>
|
||||||
|
{% else %}
|
||||||
|
<div class="col"><input type="text" class="form-control" name="last_name" placeholder="Last Name" required="required"></div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{% if form.email.value %}
|
||||||
|
<input type="text" class="form-control" name="email" value="{{ form.email.value }}">
|
||||||
|
{% else %}
|
||||||
|
<input type="email" class="form-control" name="email" placeholder="Email" required="required">
|
||||||
|
{% endif %}
|
||||||
|
<div class="form-group">{{ form.email.errors }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
{% if form.mobile.value %}
|
||||||
|
<input type="text" class="form-control" name="mobile" value="{{ form.mobile.value }}">
|
||||||
|
{% else %}
|
||||||
|
<input id="mobile" type="row" class="form-control" name="mobile" placeholder="Mobile" >
|
||||||
|
{% endif %}
|
||||||
|
<label for="mobile">Not required</label>
|
||||||
|
<div class="form-group">{{ form.mobile.errors }}</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" class="form-control" name="password1" placeholder="Password" required="required">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="password" class="form-control" name="password2" placeholder="Confirm Password" required="required">
|
||||||
|
<div class="form-group">{{ form.password2.errors }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="submit" class="btn btn-primary btn-lg">Sign Up</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">{{ form.non_field_errors }}</div>
|
||||||
|
</form>
|
||||||
|
<div class="hint-text">Already have an account? <a href="{% url 'accounts:login' %}">Login here</a></div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
3
django_accounts_app/tests.py
Normal file
3
django_accounts_app/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
10
django_accounts_app/urls.py
Normal file
10
django_accounts_app/urls.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from django.urls import path, include
|
||||||
|
from .views import dashboard, RegisterUser
|
||||||
|
|
||||||
|
app_name = 'accounts'
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
path('', include("django.contrib.auth.urls")),
|
||||||
|
path('dashboard/', dashboard, name='dashboard'),
|
||||||
|
path('registration/', RegisterUser.as_view(), name='registration')
|
||||||
|
]
|
34
django_accounts_app/views.py
Normal file
34
django_accounts_app/views.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from django.forms import BaseModelForm
|
||||||
|
from django.shortcuts import render, redirect
|
||||||
|
from django.contrib.auth import login
|
||||||
|
from django.views.generic import CreateView
|
||||||
|
from django.http import HttpResponse
|
||||||
|
from server.apps.accounts.forms import CustomUserCreationForm
|
||||||
|
from django.core.validators import validate_email
|
||||||
|
from .tasks import mail_send
|
||||||
|
|
||||||
|
|
||||||
|
# Create your views here.
|
||||||
|
def dashboard(request):
|
||||||
|
return render(request, "users/dashboard.html", {})
|
||||||
|
|
||||||
|
|
||||||
|
class RegisterUser(CreateView):
|
||||||
|
form_class = CustomUserCreationForm
|
||||||
|
template_name = 'users/register.html'
|
||||||
|
|
||||||
|
def form_valid(self, form: BaseModelForm) -> HttpResponse:
|
||||||
|
user = form.save()
|
||||||
|
user.backend = 'django.contrib.auth.backends.ModelBackend'
|
||||||
|
|
||||||
|
validate_email(form.instance.email)
|
||||||
|
email = form.instance.email
|
||||||
|
username = f'{form.instance.first_name} {form.instance.last_name}'
|
||||||
|
subject = 'Welcome to book bot administration'
|
||||||
|
mail_send(to_email=email, subject=subject, username=username)
|
||||||
|
|
||||||
|
login(self.request, user)
|
||||||
|
|
||||||
|
return redirect('admin:index')
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user