Skip to content

Commit

Permalink
Refactoring/user model (#67)
Browse files Browse the repository at this point in the history
* Refactoring User_Model

* Add django-phonenumber-field

* bugfix of mypy/added django-extensions 3.2.3

* fix flake8 mypy errors

* fix django extensions/

---------

Co-authored-by: Konstantin Raikhert <raikhert13@gmail.com>
  • Loading branch information
xxfeel and KonstantinRaikhert authored Dec 19, 2023
1 parent 1903717 commit e041655
Show file tree
Hide file tree
Showing 16 changed files with 365 additions and 124 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ ALLOWED_HOSTS=*

# Superuser settings

DJANGO_SUPERUSER_FIRST_NAME=admin
DJANGO_SUPERUSER_LAST_NAME=admin
DJANGO_SUPERUSER_ROLE=admin
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_EMAIL=admin@admin.ru
DJANGO_SUPERUSER_PASSWORD=admin
1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ repos:
additional_dependencies:
- django-stubs
- django-environ
- django-phonenumber-field[phonenumbers]

- repo: local
hooks:
Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ help:
@echo " run - $(SHELL_GREEN)Команда для локального запуска проекта.$(SHELL_NC)"
@echo " fill-db - $(SHELL_GREEN)Команда для заполнения базы данных с помощью парсера.$(SHELL_NC)"
@echo " pytest - $(SHELL_GREEN)Команда для прогона юнит тестов pytest.$(SHELL_NC)"
@echo " shell - $(SHELL_GREEN)Команда для запуска Django-shell_plus.$(SHELL_NC)"
@echo " help - $(SHELL_GREEN)Команда вызова справки.$(SHELL_NC)"
@echo "$(SHELL_YELLOW)Для запуска исполнения команд используйте данные ключи совместно с командой 'make', например 'make init-app'."
@echo "При запуске команды 'make' без какого либо ключа, происходит вызов справки.$(SHELL_NC)"
Expand Down Expand Up @@ -59,6 +60,11 @@ run:
cd $(PROJECT_DIR) && $(DJANGO_RUN) runserver


# Запуск django shell
shell:
cd $(PROJECT_DIR) && $(DJANGO_RUN) shell_plus --plain


# Заполнение базы данных с помощью парсера.
fill-db:
cd $(PROJECT_DIR) && $(DJANGO_RUN) fill-db
Expand Down
8 changes: 7 additions & 1 deletion adaptive_hockey_federation/core/config/base_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
'django.contrib.staticfiles',
]

EXTERNAL_APPS = []
EXTERNAL_APPS = [
'phonenumber_field',
]

LOCAL_APPS = [
'main.apps.MainConfig',
Expand Down Expand Up @@ -112,3 +114,7 @@
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

AUTH_USER_MODEL = 'users.User'

PHONENUMBER_DEFAULT_REGION = 'RU'

PHONENUMBER_DEFAULT_FORMAT = 'INTERNATIONAL'
6 changes: 6 additions & 0 deletions adaptive_hockey_federation/core/config/dev_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
env.read_env(ROOT_DIR / '.env')


DEV_APPS = [
'django_extensions',
]

INSTALLED_APPS += DEV_APPS

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
Expand Down
12 changes: 12 additions & 0 deletions adaptive_hockey_federation/core/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
NAME_MAX_LENGTH = 256
EMAIL_MAX_LENGTH = 256
QUERY_SET_LENGTH = 15

ROLE_AGENT = 'agent'
ROLE_MODERATOR = 'moderator'
ROLE_ADMIN = 'admin'
ROLES_CHOICES = (
(ROLE_AGENT, 'Представитель команды'),
(ROLE_MODERATOR, 'Модератор'),
(ROLE_ADMIN, 'Администратор'),
)
12 changes: 4 additions & 8 deletions adaptive_hockey_federation/users/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,16 @@ class UserAdmin(admin.ModelAdmin):
# date_hierarchy = 'date_joined'
list_display = (
'id',
'username',
'email',
'phone',
'first_name',
'last_name',
'role',
'team',
)
fields = [
'username',
'email',
'phone',
)
fields = [
('first_name', 'last_name'),
'role',
'team',
'email',
'phone',
]
empty_value_display = '-пусто-'
36 changes: 36 additions & 0 deletions adaptive_hockey_federation/users/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import gettext_lazy as _


class CustomUserManager(BaseUserManager):
"""
Кастомный менеджер модели пользователя,
где идентификатором является поле с адресом электронной почты.
"""

use_in_migrations = True

def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError(_('Предоставить адрес электронной почты.'))
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save()
return user

def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)

def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields['role'] = 'admin'
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Суперюзер должен иметь is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Суперюзер должен иметь is_superuser=True.'))

return self._create_user(email, password, **extra_fields)
160 changes: 132 additions & 28 deletions adaptive_hockey_federation/users/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,153 @@
# Generated by Django 4.2.6 on 2023-11-25 14:50
# Generated by Django 4.2.8 on 2023-12-19 14:34

import django.contrib.auth.models
import django.contrib.auth.validators
import django.db.models.deletion
import django.utils.timezone
import phonenumber_field.modelfields
import phonenumber_field.validators
import users.managers
from django.db import migrations, models


class Migration(migrations.Migration):

initial = True

dependencies = [
('main', '0001_initial'),
('auth', '0012_alter_user_first_name_max_length'),
("auth", "0012_alter_user_first_name_max_length"),
]

operations = [
migrations.CreateModel(
name='User',
name="User",
fields=[
('id', models.BigAutoField(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')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('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')),
('phone', models.CharField(max_length=20)),
('role', models.CharField(choices=[('user', 'Пользователь'), ('agent', 'Представитель команды'), ('moderator', 'Модератор'), ('admin', 'Администратор')], default='user', max_length=9)),
('first_name', models.CharField(blank=True, max_length=256, null=True)),
('last_name', models.CharField(blank=True, max_length=256, null=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')),
('team', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='users', to='main.team', verbose_name='Команда')),
('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')),
(
"id",
models.BigAutoField(
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",
),
),
(
"first_name",
models.CharField(
help_text="Имя", max_length=256, verbose_name="Имя"
),
),
(
"last_name",
models.CharField(
help_text="Фамилия", max_length=256, verbose_name="Фамилия"
),
),
(
"patronymic",
models.CharField(
blank=True,
help_text="Отчество",
max_length=256,
verbose_name="Отчество",
),
),
(
"role",
models.CharField(
choices=[
("agent", "Представитель команды"),
("moderator", "Модератор"),
("admin", "Администратор"),
],
default="agent",
help_text="Уровень прав доступа",
max_length=9,
verbose_name="Роль",
),
),
(
"email",
models.EmailField(
help_text="Электронная почта",
max_length=256,
unique=True,
verbose_name="Электронная почта",
),
),
(
"phone",
phonenumber_field.modelfields.PhoneNumberField(
blank=True,
help_text="Номер телефона, допустимый формат - +7 ХХХ ХХХ ХХ ХХ",
max_length=128,
region=None,
validators=[
phonenumber_field.validators.validate_international_phonenumber
],
verbose_name="Актуальный номер телефона",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now,
verbose_name="Дата регистрации.",
),
),
(
"is_staff",
models.BooleanField(
default=False, verbose_name="Статус администратора."
),
),
(
"is_active",
models.BooleanField(
default=True, verbose_name="Показывает статус он-лайн."
),
),
(
"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': 'Пользователь',
'verbose_name_plural': 'Пользователи',
'ordering': ('username',),
"verbose_name": "Пользователь",
"verbose_name_plural": "Пользователи",
"ordering": ("last_name",),
},
managers=[
('objects', django.contrib.auth.models.UserManager()),
("objects", users.managers.CustomUserManager()),
],
),
]

This file was deleted.

This file was deleted.

Loading

0 comments on commit e041655

Please sign in to comment.