mirror of
https://github.com/cookiecutter/cookiecutter-django.git
synced 2025-08-15 09:24:52 +03:00
Changes for the cookiecutter
This commit is contained in:
parent
b018b7b8a8
commit
e531089f3e
|
@ -112,7 +112,7 @@ AUTHENTICATION_BACKENDS = [
|
||||||
"allauth.account.auth_backends.AuthenticationBackend",
|
"allauth.account.auth_backends.AuthenticationBackend",
|
||||||
]
|
]
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#auth-user-model
|
# 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
|
# https://docs.djangoproject.com/en/dev/ref/settings/#login-redirect-url
|
||||||
LOGIN_REDIRECT_URL = "users:redirect"
|
LOGIN_REDIRECT_URL = "users:redirect"
|
||||||
# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
|
# https://docs.djangoproject.com/en/dev/ref/settings/#login-url
|
||||||
|
|
|
@ -91,9 +91,7 @@
|
||||||
<a class="nav-link" href="{% url 'about' %}">About</a>
|
<a class="nav-link" href="{% url 'about' %}">About</a>
|
||||||
</li>
|
</li>
|
||||||
{% if request.user.is_authenticated %}
|
{% if request.user.is_authenticated %}
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link" href="{% endraw %}{% if cookiecutter.username_type == "email" %}{% raw %}{% url 'users:detail' request.user.pk %}{% endraw %}{% else %}{% raw %}{% url 'users:detail' request.user.username %}{% endraw %}{% endif %}{% raw %}">{% translate "My Profile" %}</a>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
{# URL provided by django-allauth/account/urls.py #}
|
{# URL provided by django-allauth/account/urls.py #}
|
||||||
<a class="nav-link" href="{% url 'account_logout' %}">{% translate "Sign Out" %}</a>
|
<a class="nav-link" href="{% url 'account_logout' %}">{% translate "Sign Out" %}</a>
|
||||||
|
|
|
@ -3,48 +3,5 @@ from django.contrib.auth import admin as auth_admin
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.forms import UserAdminChangeForm, UserAdminCreationForm
|
|
||||||
|
|
||||||
User = get_user_model()
|
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 %}
|
|
||||||
|
|
|
@ -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.
|
|
||||||
"""
|
|
|
@ -1,34 +1,21 @@
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.contrib.auth.models import UserManager as DjangoUserManager
|
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):
|
class UserManager(BaseUserManager):
|
||||||
"""
|
def create_user(self, email, password=None, **kwargs):
|
||||||
Create and save a user with the given email and password.
|
|
||||||
"""
|
|
||||||
if not email:
|
if not email:
|
||||||
raise ValueError("The given email must be set")
|
raise ValueError('Users must have an email address')
|
||||||
email = self.normalize_email(email)
|
|
||||||
user = self.model(email=email, **extra_fields)
|
user = self.model(email=self.normalize_email(email), **kwargs)
|
||||||
user.password = make_password(password)
|
user.set_password(password)
|
||||||
user.save(using=self._db)
|
user.save(using=self._db)
|
||||||
return user
|
return user
|
||||||
|
|
||||||
def create_user(self, email: str, password: str | None = None, **extra_fields):
|
def create_superuser(self, email, password, **kwargs):
|
||||||
extra_fields.setdefault("is_staff", False)
|
kwargs.setdefault('is_staff', True)
|
||||||
extra_fields.setdefault("is_superuser", False)
|
kwargs.setdefault('is_superuser', True)
|
||||||
return self._create_user(email, password, **extra_fields)
|
return self.create_user(email, password, **kwargs)
|
||||||
|
|
||||||
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)
|
|
|
@ -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 %}
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -8,7 +8,7 @@ from {{ cookiecutter.project_slug }}.users.managers import UserManager
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
class User(AbstractUser):
|
class Account(AbstractUser):
|
||||||
"""
|
"""
|
||||||
Default custom user model for {{cookiecutter.project_name}}.
|
Default custom user model for {{cookiecutter.project_name}}.
|
||||||
If adding fields that need to be filled at user signup,
|
If adding fields that need to be filled at user signup,
|
||||||
|
|
|
@ -1,18 +1,11 @@
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
from {{ cookiecutter.project_slug }}.users.views import (
|
from {{ cookiecutter.project_slug }}.users.views import (
|
||||||
user_detail_view,
|
|
||||||
user_redirect_view,
|
user_redirect_view,
|
||||||
user_update_view,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
app_name = "users"
|
app_name = "users"
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("~redirect/", view=user_redirect_view, name="redirect"),
|
path("~redirect/", view=user_redirect_view, name="redirect"),
|
||||||
path("~update/", view=user_update_view, name="update"),
|
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
|
||||||
path("<int:pk>/", view=user_detail_view, name="detail"),
|
|
||||||
{%- else %}
|
|
||||||
path("<str:username>/", view=user_detail_view, name="detail"),
|
|
||||||
{%- endif %}
|
|
||||||
]
|
]
|
||||||
|
|
|
@ -8,34 +8,6 @@ from django.views.generic import DetailView, RedirectView, UpdateView
|
||||||
User = get_user_model()
|
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):
|
class UserRedirectView(LoginRequiredMixin, RedirectView):
|
||||||
|
@ -45,7 +17,7 @@ class UserRedirectView(LoginRequiredMixin, RedirectView):
|
||||||
{%- if cookiecutter.username_type == "email" %}
|
{%- if cookiecutter.username_type == "email" %}
|
||||||
return reverse("users:detail", kwargs={"pk": self.request.user.pk})
|
return reverse("users:detail", kwargs={"pk": self.request.user.pk})
|
||||||
{%- else %}
|
{%- else %}
|
||||||
return reverse("users:detail", kwargs={"username": self.request.user.username})
|
return reverse("users:detail", kwargs={"email": self.request.user.email})
|
||||||
{%- endif %}
|
{%- endif %}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user