├── customuser
├── core
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── admin.py
│ ├── views.py
│ └── apps.py
├── accounts
│ ├── __init__.py
│ ├── migrations
│ │ ├── __init__.py
│ │ ├── 0001_postgres_extensions.py
│ │ └── 0002_customuser.py
│ ├── admin.py
│ ├── tests.py
│ ├── views.py
│ ├── apps.py
│ └── models.py
├── customuser
│ ├── __init__.py
│ ├── asgi.py
│ ├── wsgi.py
│ ├── urls.py
│ └── settings.py
├── requirements.txt
└── manage.py
├── userworkarounds
├── core
│ ├── __init__.py
│ ├── migrations
│ │ └── __init__.py
│ ├── models.py
│ ├── tests.py
│ ├── admin.py
│ ├── apps.py
│ ├── templates
│ │ └── core
│ │ │ ├── success.html
│ │ │ └── signup.html
│ ├── views.py
│ └── forms.py
├── userworkarounds
│ ├── __init__.py
│ ├── asgi.py
│ ├── wsgi.py
│ ├── backends.py
│ ├── urls.py
│ └── settings.py
├── requirements.txt
└── manage.py
└── .gitignore
/customuser/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/customuser/accounts/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/customuser/customuser/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/userworkarounds/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/customuser/core/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/customuser/accounts/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/userworkarounds/core/migrations/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/userworkarounds/userworkarounds/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/userworkarounds/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==3.2.5
2 |
--------------------------------------------------------------------------------
/customuser/requirements.txt:
--------------------------------------------------------------------------------
1 | Django==3.2.5
2 | psycopg2-binary==2.9.1
3 |
--------------------------------------------------------------------------------
/customuser/core/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/customuser/core/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/customuser/accounts/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/customuser/accounts/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/customuser/accounts/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 |
--------------------------------------------------------------------------------
/customuser/core/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/customuser/core/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render
2 |
3 | # Create your views here.
4 |
--------------------------------------------------------------------------------
/userworkarounds/core/models.py:
--------------------------------------------------------------------------------
1 | from django.db import models
2 |
3 | # Create your models here.
4 |
--------------------------------------------------------------------------------
/userworkarounds/core/tests.py:
--------------------------------------------------------------------------------
1 | from django.test import TestCase
2 |
3 | # Create your tests here.
4 |
--------------------------------------------------------------------------------
/userworkarounds/core/admin.py:
--------------------------------------------------------------------------------
1 | from django.contrib import admin
2 |
3 | # Register your models here.
4 |
--------------------------------------------------------------------------------
/customuser/core/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class CoreConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "core"
7 |
--------------------------------------------------------------------------------
/userworkarounds/core/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class CoreConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "core"
7 |
--------------------------------------------------------------------------------
/customuser/accounts/apps.py:
--------------------------------------------------------------------------------
1 | from django.apps import AppConfig
2 |
3 |
4 | class AccountsConfig(AppConfig):
5 | default_auto_field = "django.db.models.BigAutoField"
6 | name = "accounts"
7 |
--------------------------------------------------------------------------------
/userworkarounds/core/templates/core/success.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Success!
6 |
7 |
8 |
9 | User account created with success!
10 |
11 |
12 |
--------------------------------------------------------------------------------
/customuser/accounts/migrations/0001_postgres_extensions.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.5 on 2021-07-08 20:33
2 | from django.contrib.postgres.operations import CITextExtension
3 | from django.db import migrations
4 |
5 |
6 | class Migration(migrations.Migration):
7 |
8 | dependencies = []
9 |
10 | operations = [CITextExtension()]
11 |
--------------------------------------------------------------------------------
/userworkarounds/core/templates/core/signup.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Django Signup Example
5 |
6 |
7 |
8 | Sign up form
9 |
10 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/customuser/customuser/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for customuser project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "customuser.settings")
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/customuser/customuser/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for customuser project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "customuser.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/userworkarounds/userworkarounds/asgi.py:
--------------------------------------------------------------------------------
1 | """
2 | ASGI config for userworkarounds project.
3 |
4 | It exposes the ASGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.asgi import get_asgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "userworkarounds.settings")
15 |
16 | application = get_asgi_application()
17 |
--------------------------------------------------------------------------------
/userworkarounds/userworkarounds/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for userworkarounds project.
3 |
4 | It exposes the WSGI callable as a module-level variable named ``application``.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
8 | """
9 |
10 | import os
11 |
12 | from django.core.wsgi import get_wsgi_application
13 |
14 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "userworkarounds.settings")
15 |
16 | application = get_wsgi_application()
17 |
--------------------------------------------------------------------------------
/userworkarounds/core/views.py:
--------------------------------------------------------------------------------
1 | from django.shortcuts import render, redirect
2 |
3 | from core.forms import UserCreationForm
4 |
5 |
6 | def signup(request):
7 | if request.method == "POST":
8 | form = UserCreationForm(request.POST)
9 | if form.is_valid():
10 | form.save()
11 | return redirect("success")
12 | else:
13 | form = UserCreationForm()
14 | return render(request, "core/signup.html", {"form": form})
15 |
16 |
17 | def success(request):
18 | return render(request, "core/success.html")
19 |
--------------------------------------------------------------------------------
/customuser/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "customuser.settings")
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == "__main__":
22 | main()
23 |
--------------------------------------------------------------------------------
/userworkarounds/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | """Django's command-line utility for administrative tasks."""
3 | import os
4 | import sys
5 |
6 |
7 | def main():
8 | """Run administrative tasks."""
9 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "userworkarounds.settings")
10 | try:
11 | from django.core.management import execute_from_command_line
12 | except ImportError as exc:
13 | raise ImportError(
14 | "Couldn't import Django. Are you sure it's installed and "
15 | "available on your PYTHONPATH environment variable? Did you "
16 | "forget to activate a virtual environment?"
17 | ) from exc
18 | execute_from_command_line(sys.argv)
19 |
20 |
21 | if __name__ == "__main__":
22 | main()
23 |
--------------------------------------------------------------------------------
/customuser/customuser/urls.py:
--------------------------------------------------------------------------------
1 | """customuser URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path
18 |
19 | urlpatterns = [
20 | path("admin/", admin.site.urls),
21 | ]
22 |
--------------------------------------------------------------------------------
/userworkarounds/userworkarounds/backends.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth import get_user_model
2 | from django.contrib.auth.backends import ModelBackend
3 |
4 |
5 | class CaseInsensitiveModelBackend(ModelBackend):
6 | def authenticate(self, request, username=None, password=None, **kwargs):
7 | UserModel = get_user_model()
8 | if username is None:
9 | username = kwargs.get(UserModel.USERNAME_FIELD)
10 | try:
11 | case_insensitive_username_field = "{}__iexact".format(UserModel.USERNAME_FIELD)
12 | user = UserModel._default_manager.get(**{case_insensitive_username_field: username})
13 | except UserModel.DoesNotExist:
14 | # Run the default password hasher once to reduce the timing
15 | # difference between an existing and a non-existing user (#20760).
16 | UserModel().set_password(password)
17 | else:
18 | if user.check_password(password) and self.user_can_authenticate(user):
19 | return user
20 |
--------------------------------------------------------------------------------
/userworkarounds/userworkarounds/urls.py:
--------------------------------------------------------------------------------
1 | """userworkarounds URL Configuration
2 |
3 | The `urlpatterns` list routes URLs to views. For more information please see:
4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/
5 | Examples:
6 | Function views
7 | 1. Add an import: from my_app import views
8 | 2. Add a URL to urlpatterns: path('', views.home, name='home')
9 | Class-based views
10 | 1. Add an import: from other_app.views import Home
11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
12 | Including another URLconf
13 | 1. Import the include() function: from django.urls import include, path
14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
15 | """
16 | from django.contrib import admin
17 | from django.urls import path
18 | from django.views.generic import RedirectView
19 |
20 | from core import views
21 |
22 |
23 | urlpatterns = [
24 | path("", RedirectView.as_view(pattern_name="signup"), name="home"),
25 | path("signup/", views.signup, name="signup"),
26 | path("success/", views.success, name="success"),
27 | path("admin/", admin.site.urls),
28 | ]
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
131 | .DS_Store
132 | .idea/
133 |
134 | node_modules/
135 |
--------------------------------------------------------------------------------
/customuser/accounts/models.py:
--------------------------------------------------------------------------------
1 | from django.contrib.auth.base_user import AbstractBaseUser
2 | from django.contrib.auth.models import PermissionsMixin, UserManager
3 | from django.contrib.auth.validators import ASCIIUsernameValidator
4 | from django.contrib.postgres.fields import CICharField, CIEmailField
5 | from django.core.mail import send_mail
6 | from django.db import models
7 | from django.utils import timezone
8 | from django.utils.translation import gettext_lazy as _
9 |
10 |
11 | class CustomUser(AbstractBaseUser, PermissionsMixin):
12 | username_validator = ASCIIUsernameValidator()
13 |
14 | username = CICharField(
15 | _("username"),
16 | max_length=150,
17 | unique=True,
18 | help_text=_("Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."),
19 | validators=[username_validator],
20 | error_messages={
21 | "unique": _("A user with that username already exists."),
22 | },
23 | )
24 | first_name = models.CharField(_("first name"), max_length=150, blank=True)
25 | last_name = models.CharField(_("last name"), max_length=150, blank=True)
26 | email = CIEmailField(
27 | _("email address"),
28 | unique=True,
29 | error_messages={
30 | "unique": _("A user with that email address already exists."),
31 | },
32 | )
33 | is_staff = models.BooleanField(
34 | _("staff status"),
35 | default=False,
36 | help_text=_("Designates whether the user can log into this admin site."),
37 | )
38 | is_active = models.BooleanField(
39 | _("active"),
40 | default=True,
41 | help_text=_(
42 | "Designates whether this user should be treated as active. Unselect this instead of deleting accounts."
43 | ),
44 | )
45 | date_joined = models.DateTimeField(_("date joined"), default=timezone.now)
46 |
47 | objects = UserManager()
48 |
49 | EMAIL_FIELD = "email"
50 | USERNAME_FIELD = "username"
51 | REQUIRED_FIELDS = ["email"]
52 |
53 | class Meta:
54 | verbose_name = _("user")
55 | verbose_name_plural = _("users")
56 |
57 | def clean(self):
58 | super().clean()
59 | self.email = self.__class__.objects.normalize_email(self.email)
60 |
61 | def get_full_name(self):
62 | """
63 | Return the first_name plus the last_name, with a space in between.
64 | """
65 | full_name = "%s %s" % (self.first_name, self.last_name)
66 | return full_name.strip()
67 |
68 | def get_short_name(self):
69 | """Return the short name for the user."""
70 | return self.first_name
71 |
72 | def email_user(self, subject, message, from_email=None, **kwargs):
73 | """Send an email to this user."""
74 | send_mail(subject, message, from_email, [self.email], **kwargs)
75 |
--------------------------------------------------------------------------------
/customuser/accounts/migrations/0002_customuser.py:
--------------------------------------------------------------------------------
1 | # Generated by Django 3.2.5 on 2021-07-08 20:59
2 |
3 | import django.contrib.auth.models
4 | import django.contrib.auth.validators
5 | import django.contrib.postgres.fields.citext
6 | from django.db import migrations, models
7 | import django.utils.timezone
8 |
9 |
10 | class Migration(migrations.Migration):
11 |
12 | initial = True
13 |
14 | dependencies = [
15 | ('auth', '0012_alter_user_first_name_max_length'),
16 | ('accounts', '0001_postgres_extensions'),
17 | ]
18 |
19 | operations = [
20 | migrations.CreateModel(
21 | name='CustomUser',
22 | fields=[
23 | ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24 | ('password', models.CharField(max_length=128, verbose_name='password')),
25 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
26 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
27 | ('username', django.contrib.postgres.fields.citext.CICharField(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.ASCIIUsernameValidator()], verbose_name='username')),
28 | ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
29 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
30 | ('email', django.contrib.postgres.fields.citext.CIEmailField(error_messages={'unique': 'A user with that email address already exists.'}, max_length=254, unique=True, verbose_name='email address')),
31 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
32 | ('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')),
33 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
34 | ('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')),
35 | ('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')),
36 | ],
37 | options={
38 | 'verbose_name': 'user',
39 | 'verbose_name_plural': 'users',
40 | },
41 | managers=[
42 | ('objects', django.contrib.auth.models.UserManager()),
43 | ],
44 | ),
45 | ]
46 |
--------------------------------------------------------------------------------
/userworkarounds/core/forms.py:
--------------------------------------------------------------------------------
1 | from django import forms
2 | from django.contrib.auth import password_validation, get_user_model
3 | from django.contrib.auth.forms import UsernameField
4 | from django.contrib.auth.validators import ASCIIUsernameValidator
5 | from django.core.exceptions import ValidationError
6 | from django.utils.translation import gettext_lazy as _
7 |
8 |
9 | User = get_user_model()
10 |
11 |
12 | class ASCIIUsernameField(UsernameField):
13 | def __init__(self, *args, **kwargs):
14 | super().__init__(*args, **kwargs)
15 | self.validators.append(ASCIIUsernameValidator())
16 |
17 |
18 | class UserCreationForm(forms.ModelForm):
19 | """
20 | A form that creates a user, with no privileges, from the given username and
21 | password.
22 | """
23 |
24 | error_messages = {
25 | "password_mismatch": _("The two password fields didn’t match."),
26 | }
27 | password1 = forms.CharField(
28 | label=_("Password"),
29 | strip=False,
30 | widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
31 | help_text=password_validation.password_validators_help_text_html(),
32 | )
33 | password2 = forms.CharField(
34 | label=_("Password confirmation"),
35 | widget=forms.PasswordInput(attrs={"autocomplete": "new-password"}),
36 | strip=False,
37 | help_text=_("Enter the same password as before, for verification."),
38 | )
39 | email = forms.EmailField(label=_("Email address"), required=True)
40 |
41 | class Meta:
42 | model = User
43 | fields = ("username", "email", "password1", "password2")
44 | field_classes = {"username": ASCIIUsernameField}
45 |
46 | def __init__(self, *args, **kwargs):
47 | super().__init__(*args, **kwargs)
48 | if self._meta.model.USERNAME_FIELD in self.fields:
49 | self.fields[self._meta.model.USERNAME_FIELD].widget.attrs["autofocus"] = True
50 |
51 | def clean_username(self):
52 | username = self.cleaned_data.get("username")
53 | if User.objects.filter(username__iexact=username).exists():
54 | self.add_error("username", _("A user with this username already exists."))
55 | return username
56 |
57 | def clean_email(self):
58 | email = self.cleaned_data.get("email")
59 | if User.objects.filter(email__iexact=email).exists():
60 | self.add_error("email", _("A user with this email already exists."))
61 | return email
62 |
63 | def clean_password2(self):
64 | password1 = self.cleaned_data.get("password1")
65 | password2 = self.cleaned_data.get("password2")
66 | if password1 and password2 and password1 != password2:
67 | raise ValidationError(
68 | self.error_messages["password_mismatch"],
69 | code="password_mismatch",
70 | )
71 | return password2
72 |
73 | def _post_clean(self):
74 | super()._post_clean()
75 | # Validate the password after self.instance is updated with form data
76 | # by super().
77 | password = self.cleaned_data.get("password2")
78 | if password:
79 | try:
80 | password_validation.validate_password(password, self.instance)
81 | except ValidationError as error:
82 | self.add_error("password2", error)
83 |
84 | def save(self, commit=True):
85 | user = super().save(commit=False)
86 | user.set_password(self.cleaned_data["password1"])
87 | if commit:
88 | user.save()
89 | return user
90 |
--------------------------------------------------------------------------------
/userworkarounds/userworkarounds/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for userworkarounds project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.5.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = "django-insecure-^cb@_z4jom59tr#@kcn1nan!xhdjn_s5=3j-w_y_q^isas7c)b"
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | "django.contrib.admin",
35 | "django.contrib.auth",
36 | "django.contrib.contenttypes",
37 | "django.contrib.sessions",
38 | "django.contrib.messages",
39 | "django.contrib.staticfiles",
40 | "core",
41 | ]
42 |
43 | MIDDLEWARE = [
44 | "django.middleware.security.SecurityMiddleware",
45 | "django.contrib.sessions.middleware.SessionMiddleware",
46 | "django.middleware.common.CommonMiddleware",
47 | "django.middleware.csrf.CsrfViewMiddleware",
48 | "django.contrib.auth.middleware.AuthenticationMiddleware",
49 | "django.contrib.messages.middleware.MessageMiddleware",
50 | "django.middleware.clickjacking.XFrameOptionsMiddleware",
51 | ]
52 |
53 | ROOT_URLCONF = "userworkarounds.urls"
54 |
55 | TEMPLATES = [
56 | {
57 | "BACKEND": "django.template.backends.django.DjangoTemplates",
58 | "DIRS": [],
59 | "APP_DIRS": True,
60 | "OPTIONS": {
61 | "context_processors": [
62 | "django.template.context_processors.debug",
63 | "django.template.context_processors.request",
64 | "django.contrib.auth.context_processors.auth",
65 | "django.contrib.messages.context_processors.messages",
66 | ],
67 | },
68 | },
69 | ]
70 |
71 | WSGI_APPLICATION = "userworkarounds.wsgi.application"
72 |
73 |
74 | # Database
75 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
76 |
77 | DATABASES = {
78 | "default": {
79 | "ENGINE": "django.db.backends.sqlite3",
80 | "NAME": BASE_DIR / "db.sqlite3",
81 | }
82 | }
83 |
84 |
85 | # Password validation
86 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
87 |
88 | AUTH_PASSWORD_VALIDATORS = [
89 | {
90 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
91 | },
92 | {
93 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
94 | },
95 | {
96 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
97 | },
98 | {
99 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
100 | },
101 | ]
102 |
103 |
104 | # Internationalization
105 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
106 |
107 | LANGUAGE_CODE = "en-us"
108 |
109 | TIME_ZONE = "UTC"
110 |
111 | USE_I18N = True
112 |
113 | USE_L10N = True
114 |
115 | USE_TZ = True
116 |
117 |
118 | # Static files (CSS, JavaScript, Images)
119 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
120 |
121 | STATIC_URL = "/static/"
122 |
123 | # Default primary key field type
124 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
125 |
126 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
127 |
128 |
129 | AUTHENTICATION_BACKENDS = ("userworkarounds.backends.CaseInsensitiveModelBackend",)
130 |
--------------------------------------------------------------------------------
/customuser/customuser/settings.py:
--------------------------------------------------------------------------------
1 | """
2 | Django settings for customuser project.
3 |
4 | Generated by 'django-admin startproject' using Django 3.2.5.
5 |
6 | For more information on this file, see
7 | https://docs.djangoproject.com/en/3.2/topics/settings/
8 |
9 | For the full list of settings and their values, see
10 | https://docs.djangoproject.com/en/3.2/ref/settings/
11 | """
12 |
13 | from pathlib import Path
14 |
15 | # Build paths inside the project like this: BASE_DIR / 'subdir'.
16 | BASE_DIR = Path(__file__).resolve().parent.parent
17 |
18 |
19 | # Quick-start development settings - unsuitable for production
20 | # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
21 |
22 | # SECURITY WARNING: keep the secret key used in production secret!
23 | SECRET_KEY = "django-insecure-2w+_&5mf$13wh9c#w#s9r-0ot(x=!+x0srn=39n1kepba!vv)i"
24 |
25 | # SECURITY WARNING: don't run with debug turned on in production!
26 | DEBUG = True
27 |
28 | ALLOWED_HOSTS = []
29 |
30 |
31 | # Application definition
32 |
33 | INSTALLED_APPS = [
34 | "django.contrib.admin",
35 | "django.contrib.auth",
36 | "django.contrib.contenttypes",
37 | "django.contrib.sessions",
38 | "django.contrib.messages",
39 | "django.contrib.staticfiles",
40 | "accounts",
41 | "core",
42 | ]
43 |
44 | MIDDLEWARE = [
45 | "django.middleware.security.SecurityMiddleware",
46 | "django.contrib.sessions.middleware.SessionMiddleware",
47 | "django.middleware.common.CommonMiddleware",
48 | "django.middleware.csrf.CsrfViewMiddleware",
49 | "django.contrib.auth.middleware.AuthenticationMiddleware",
50 | "django.contrib.messages.middleware.MessageMiddleware",
51 | "django.middleware.clickjacking.XFrameOptionsMiddleware",
52 | ]
53 |
54 | ROOT_URLCONF = "customuser.urls"
55 |
56 | TEMPLATES = [
57 | {
58 | "BACKEND": "django.template.backends.django.DjangoTemplates",
59 | "DIRS": [],
60 | "APP_DIRS": True,
61 | "OPTIONS": {
62 | "context_processors": [
63 | "django.template.context_processors.debug",
64 | "django.template.context_processors.request",
65 | "django.contrib.auth.context_processors.auth",
66 | "django.contrib.messages.context_processors.messages",
67 | ],
68 | },
69 | },
70 | ]
71 |
72 | WSGI_APPLICATION = "customuser.wsgi.application"
73 |
74 |
75 | # Database
76 | # https://docs.djangoproject.com/en/3.2/ref/settings/#databases
77 |
78 | DATABASES = {
79 | "default": {
80 | "ENGINE": "django.db.backends.postgresql",
81 | "NAME": "customuser",
82 | "USER": "u_simple",
83 | "PASSWORD": "123",
84 | "HOST": "127.0.0.1",
85 | "PORT": "5432",
86 | }
87 | }
88 |
89 |
90 | # Password validation
91 | # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
92 |
93 | AUTH_PASSWORD_VALIDATORS = [
94 | {
95 | "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
96 | },
97 | {
98 | "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
99 | },
100 | {
101 | "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
102 | },
103 | {
104 | "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
105 | },
106 | ]
107 |
108 |
109 | # Internationalization
110 | # https://docs.djangoproject.com/en/3.2/topics/i18n/
111 |
112 | LANGUAGE_CODE = "en-us"
113 |
114 | TIME_ZONE = "UTC"
115 |
116 | USE_I18N = True
117 |
118 | USE_L10N = True
119 |
120 | USE_TZ = True
121 |
122 |
123 | # Static files (CSS, JavaScript, Images)
124 | # https://docs.djangoproject.com/en/3.2/howto/static-files/
125 |
126 | STATIC_URL = "/static/"
127 |
128 | # Default primary key field type
129 | # https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
130 |
131 | DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
132 |
133 | AUTH_USER_MODEL = "accounts.CustomUser"
134 |
--------------------------------------------------------------------------------