diff --git a/{{cookiecutter.project_slug}}/config/settings/base.py b/{{cookiecutter.project_slug}}/config/settings/base.py
index c0ca31f36..409a10cdc 100644
--- a/{{cookiecutter.project_slug}}/config/settings/base.py
+++ b/{{cookiecutter.project_slug}}/config/settings/base.py
@@ -112,7 +112,7 @@ AUTHENTICATION_BACKENDS = [
"allauth.account.auth_backends.AuthenticationBackend",
]
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
-AUTH_USER_MODEL = "users.User"
+AUTH_USER_MODEL = "users.Account"
# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
LOGIN_REDIRECT_URL = "users:redirect"
# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html
index ad51a6e18..3b07dae93 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/templates/base.html
@@ -91,9 +91,7 @@
About
{% if request.user.is_authenticated %}
-
- {% translate "My Profile" %}
-
+
{# URL provided by django-allauth/account/urls.py #}
{% translate "Sign Out" %}
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py
index d81c0a3b0..3c9b1d711 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/admin.py
@@ -3,48 +3,5 @@ from django.contrib.auth import admin as auth_admin
from django.contrib.auth import get_user_model
from django.utils.translation import gettext_lazy as _
-from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm
-
User = get_user_model()
-
-@admin.register(User)
-class UserAdmin(auth_admin.UserAdmin):
- form = UserAdminChangeForm
- add_form = UserAdminCreationForm
- fieldsets = (
- {%- if cookiecutter.username_type == "email" %}
- (None, {"fields": ("email", "password")}),
- (_("Personal info"), {"fields": ("name",)}),
- {%- else %}
- (None, {"fields": ("username", "password")}),
- (_("Personal info"), {"fields": ("name", "email")}),
- {%- endif %}
- (
- _("Permissions"),
- {
- "fields": (
- "is_active",
- "is_staff",
- "is_superuser",
- "groups",
- "user_permissions",
- ),
- },
- ),
- (_("Important dates"), {"fields": ("last_login", "date_joined")}),
- )
- list_display = ["{{cookiecutter.username_type}}", "name", "is_superuser"]
- search_fields = ["name"]
- {%- if cookiecutter.username_type == "email" %}
- ordering = ["id"]
- add_fieldsets = (
- (
- None,
- {
- "classes": ("wide",),
- "fields": ("email", "password1", "password2"),
- },
- ),
- )
- {%- endif %}
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py
index ac5b647d3..e69de29bb 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/forms.py
@@ -1,55 +0,0 @@
-from allauth.account.forms import SignupForm
-from allauth.socialaccount.forms import SignupForm as SocialSignupForm
-from django.contrib.auth import forms as admin_forms
-from django.contrib.auth import get_user_model
-{%- if cookiecutter.username_type == "email" %}
-from django.forms import EmailField
-{%- endif %}
-from django.utils.translation import gettext_lazy as _
-
-User = get_user_model()
-
-
-class UserAdminChangeForm(admin_forms.UserChangeForm):
- class Meta(admin_forms.UserChangeForm.Meta):
- model = User
- {%- if cookiecutter.username_type == "email" %}
- field_classes = {"email": EmailField}
- {%- endif %}
-
-
-class UserAdminCreationForm(admin_forms.UserCreationForm):
- """
- Form for User Creation in the Admin Area.
- To change user signup, see UserSignupForm and UserSocialSignupForm.
- """
-
- class Meta(admin_forms.UserCreationForm.Meta):
- model = User
- {%- if cookiecutter.username_type == "email" %}
- fields = ("email",)
- field_classes = {"email": EmailField}
- error_messages = {
- "email": {"unique": _("This email has already been taken.")},
- }
- {%- else %}
- error_messages = {
- "username": {"unique": _("This username has already been taken.")},
- }
- {%- endif %}
-
-
-class UserSignupForm(SignupForm):
- """
- Form that will be rendered on a user sign up section/screen.
- Default fields will be added automatically.
- Check UserSocialSignupForm for accounts created from social.
- """
-
-
-class UserSocialSignupForm(SocialSignupForm):
- """
- Renders the form when user has signed up using social accounts.
- Default fields will be added automatically.
- See UserSignupForm otherwise.
- """
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/managers.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/managers.py
index 017ab14e7..55a4cdfe3 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/managers.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/managers.py
@@ -1,34 +1,21 @@
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import UserManager as DjangoUserManager
+from django.contrib.auth.models import AbstractBaseUser
+from django.contrib.auth.models import BaseUserManager
-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.
- """
+class UserManager(BaseUserManager):
+ def create_user(self, email, password=None, **kwargs):
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)
+ raise ValueError('Users must have an email address')
+
+ user = self.model(email=self.normalize_email(email), **kwargs)
+ user.set_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)
+ def create_superuser(self, email, password, **kwargs):
+ kwargs.setdefault('is_staff', True)
+ kwargs.setdefault('is_superuser', True)
+ return self.create_user(email, password, **kwargs)
\ No newline at end of file
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py
deleted file mode 100644
index 58a439c5d..000000000
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/0001_initial.py
+++ /dev/null
@@ -1,139 +0,0 @@
-import django.contrib.auth.models
-import django.contrib.auth.validators
-from django.db import migrations, models
-import django.utils.timezone
-
-import {{cookiecutter.project_slug}}.users.models
-
-
-class Migration(migrations.Migration):
-
- initial = True
-
- dependencies = [
- ("auth", "0012_alter_user_first_name_max_length"),
- ]
-
- operations = [
- migrations.CreateModel(
- 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",
- ),
- ),
- {%- if cookiecutter.username_type == "username" -%}
- (
- "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"
- ),
- ),
- {%- else %}
- (
- "email",
- models.EmailField(
- unique=True, max_length=254, verbose_name="email address"
- ),
- ),
- {%- endif %}
- (
- "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"
- ),
- ),
- (
- "name",
- models.CharField(
- blank=True, max_length=255, verbose_name="Name of User"
- ),
- ),
- (
- "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,
- },
- managers=[
- {%- if cookiecutter.username_type == "email" %}
- ("objects", {{cookiecutter.project_slug}}.users.models.UserManager()),
- {%- else %}
- ("objects", django.contrib.auth.models.UserManager()),
- {%- endif %}
- ],
- ),
- ]
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/__init__.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/migrations/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py
index 1e4807510..48c8bd46f 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/models.py
@@ -8,7 +8,7 @@ from {{ cookiecutter.project_slug }}.users.managers import UserManager
{%- endif %}
-class User(AbstractUser):
+class Account(AbstractUser):
"""
Default custom user model for {{cookiecutter.project_name}}.
If adding fields that need to be filled at user signup,
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py
index 0ffca17aa..fe1f69582 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/urls.py
@@ -1,18 +1,11 @@
from django.urls import path
from {{ cookiecutter.project_slug }}.users.views import (
- user_detail_view,
user_redirect_view,
- user_update_view,
)
app_name = "users"
urlpatterns = [
path("~redirect/", view=user_redirect_view, name="redirect"),
- path("~update/", view=user_update_view, name="update"),
- {%- if cookiecutter.username_type == "email" %}
- path("/", view=user_detail_view, name="detail"),
- {%- else %}
- path("/", view=user_detail_view, name="detail"),
- {%- endif %}
+
]
diff --git a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py
index 82498e630..772c2cb8f 100644
--- a/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py
+++ b/{{cookiecutter.project_slug}}/{{cookiecutter.project_slug}}/users/views.py
@@ -8,34 +8,6 @@ from django.views.generic import DetailView, RedirectView, UpdateView
User = get_user_model()
-class UserDetailView(LoginRequiredMixin, DetailView):
- model = User
- {%- if cookiecutter.username_type == "email" %}
- slug_field = "id"
- slug_url_kwarg = "id"
- {%- else %}
- slug_field = "username"
- slug_url_kwarg = "username"
- {%- endif %}
-
-
-user_detail_view = UserDetailView.as_view()
-
-
-class UserUpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
- model = User
- fields = ["name"]
- success_message = _("Information successfully updated")
-
- def get_success_url(self):
- assert self.request.user.is_authenticated # for mypy to know that the user is authenticated
- return self.request.user.get_absolute_url()
-
- def get_object(self):
- return self.request.user
-
-
-user_update_view = UserUpdateView.as_view()
class UserRedirectView(LoginRequiredMixin, RedirectView):
@@ -45,7 +17,7 @@ class UserRedirectView(LoginRequiredMixin, RedirectView):
{%- if cookiecutter.username_type == "email" %}
return reverse("users:detail", kwargs={"pk": self.request.user.pk})
{%- else %}
- return reverse("users:detail", kwargs={"username": self.request.user.username})
+ return reverse("users:detail", kwargs={"email": self.request.user.email})
{%- endif %}