Move custom manager into a separate module and add tests

This commit is contained in:
Bruno Alla 2023-04-05 12:26:38 +01:00
parent 2c5668cd1b
commit 22d2087b4f
No known key found for this signature in database
4 changed files with 115 additions and 41 deletions

View File

@ -45,6 +45,24 @@ def remove_gplv3_files():
os.remove(file_name) os.remove(file_name)
def remove_custom_user_manager_files():
os.remove(
os.path.join(
"{{cookiecutter.project_slug}}",
"users",
"managers.py",
)
)
os.remove(
os.path.join(
"{{cookiecutter.project_slug}}",
"users",
"tests",
"test_managers.py",
)
)
def remove_pycharm_files(): def remove_pycharm_files():
idea_dir_path = ".idea" idea_dir_path = ".idea"
if os.path.exists(idea_dir_path): if os.path.exists(idea_dir_path):
@ -441,6 +459,9 @@ def main():
if "{{ cookiecutter.open_source_license}}" != "GPLv3": if "{{ cookiecutter.open_source_license}}" != "GPLv3":
remove_gplv3_files() remove_gplv3_files()
if "{{ cookiecutter.username_type }}" == "username":
remove_custom_user_manager_files()
if "{{ cookiecutter.use_pycharm }}".lower() == "n": if "{{ cookiecutter.use_pycharm }}".lower() == "n":
remove_pycharm_files() remove_pycharm_files()

View File

@ -0,0 +1,34 @@
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import UserManager as DjangoUserManager
class UserManager(DjangoUserManager):
"""Custom manager for the User model."""
def _create_user(self, email: str, password: str | None, **extra_fields):
"""
Create and save a user with the given email and password.
"""
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
def create_user(self, email: str, password: str | None = 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: str, password: str | None = None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", 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(email, password, **extra_fields)

View File

@ -1,44 +1,10 @@
{%- if cookiecutter.username_type == "email" -%}
from django.contrib.auth.hashers import make_password
{% endif -%}
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
{%- if cookiecutter.username_type == "email" %}
from django.contrib.auth.models import UserManager as DjangoUserManager
{%- endif %}
from django.db.models import CharField{% if cookiecutter.username_type == "email" %}, EmailField{% endif %} from django.db.models import CharField{% if cookiecutter.username_type == "email" %}, EmailField{% endif %}
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
{%- if cookiecutter.username_type == "email" %} {%- if cookiecutter.username_type == "email" %}
from {{ cookiecutter.project_slug }}.users.managers import UserManager
class UserManager(DjangoUserManager):
def _create_user(self, email, password, **extra_fields):
"""
Create and save a user with the given email and password.
"""
if not email:
raise ValueError("The given email must be set")
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
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=None, **extra_fields):
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", 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(email, password, **extra_fields)
{%- endif %} {%- endif %}
@ -49,16 +15,14 @@ class User(AbstractUser):
check forms.SignupForm and forms.SocialSignupForms accordingly. check forms.SignupForm and forms.SocialSignupForms accordingly.
""" """
#: First and last name do not cover name patterns around the globe # First and last name do not cover name patterns around the globe
name = CharField(_("Name of User"), blank=True, max_length=255) name = CharField(_("Name of User"), blank=True, max_length=255)
{%- if cookiecutter.username_type == "email" %}
username = None # type: ignore
email = EmailField(_("email address"), unique=True)
{%- endif %}
first_name = None # type: ignore first_name = None # type: ignore
last_name = None # type: ignore last_name = None # type: ignore
{%- if cookiecutter.username_type == "email" %} {%- if cookiecutter.username_type == "email" %}
email = EmailField(_("email address"), unique=True)
username = None # type: ignore
USERNAME_FIELD = "email" USERNAME_FIELD = "email"
REQUIRED_FIELDS = [] REQUIRED_FIELDS = []

View File

@ -0,0 +1,55 @@
from io import StringIO
import pytest
from django.core.management import call_command
from {{ cookiecutter.project_slug }}.users.models import User
@pytest.mark.django_db
class TestUserManager:
def test_create_user(self):
user = User.objects.create_user(
email="john@example.com",
password="something-r@nd0m!",
)
assert user.email == "john@example.com"
assert not user.is_staff
assert not user.is_superuser
assert user.check_password("something-r@nd0m!")
assert user.username is None
def test_create_superuser(self):
user = User.objects.create_superuser(
email="admin@example.com",
password="something-r@nd0m!",
)
assert user.email == "admin@example.com"
assert user.is_staff
assert user.is_superuser
assert user.username is None
def test_create_superuser_username_ignored(self):
user = User.objects.create_superuser(
email="test@example.com",
password="something-r@nd0m!",
)
assert user.username is None
@pytest.mark.django_db
def test_createsuperuser_command():
"""Ensure createsuperuser command works with our custom manager."""
out = StringIO()
command_result = call_command(
"createsuperuser",
"--email",
"henry@example.com",
interactive=False,
stdout=out,
)
assert command_result is None
assert out.getvalue() == "Superuser created successfully.\n"
user = User.objects.get(email="henry@example.com")
assert not user.has_usable_password()