Личный кабинет в Django: частые ошибки новичков
Регистрация, вход, профиль и смена пароля на Django 5.x — рабочий минимум за пару часов и разбор ошибок, из-за которых кабинет либо не открывается, либо открывается чужому пользователю.

За пару часов вы соберёте личный кабинет на Django 5.x: страницы регистрации, входа, выхода, просмотра и редактирования профиля, смены пароля. В конце — раздел «если не получилось» с текстами ошибок, которые вы реально увидите в консоли. Код рабочий, копируется целиком. Django-шаблоны, стандартная модель User, минимум сторонних пакетов.
Кабинет — это не одна страница, а связка «модель — представление — маршрут — шаблон» плюс защита от чужих глаз. Новички чаще всего спотыкаются именно на защите: страница профиля открывается по прямой ссылке любому, включая анонима. Разберём по шагам.
Что нужно до начала
- Python 3.10+ и установленный Django 5.x. Проверьте:
python -m django --versionдолжно вывести номер вида5.1.x. - Созданный проект и хотя бы одно приложение. Если проекта нет:
django-admin startproject mysite, затемpython manage.py startapp accounts. - Приложение
accountsдобавлено вINSTALLED_APPSвsettings.py. - Выполнены базовые миграции:
python manage.py migrate— иначе таблицы пользователей не существует и вход упадёт.
Работаем со встроенной моделью django.contrib.auth.models.User. Замену на кастомную модель через AUTH_USER_MODEL здесь не трогаем — это отдельная тема, и менять её после первой миграции больно.
Шаг 1. Подключаем готовые маршруты аутентификации
Django уже содержит вход, выход и смену пароля. Не пишите их руками — подключите готовый набор. В корневом urls.py:
# mysite/urls.py — Django 5.x
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
# готовые вьюхи: login, logout, password_change, password_reset и др.
path('accounts/', include('django.contrib.auth.urls')),
path('accounts/', include('accounts.urls')),
]
Проверка: откройте /accounts/login/. Вы увидите TemplateDoesNotExist: registration/login.html — это нормально, шаблон добавим на шаге 3. Главное, что маршрут найден, а не 404.
Шаг 2. Регистрация нового пользователя
Регистрации среди готовых вьюх нет — её пишем сами. Используем встроенную форму UserCreationForm.
# accounts/views.py — Django 5.x
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
user = form.save()
login(request, user) # сразу авторизуем после регистрации
return redirect('profile')
else:
form = UserCreationForm()
return render(request, 'registration/signup.html', {'form': form})
@login_required
def profile(request):
return render(request, 'accounts/profile.html')
Маршруты приложения:
# accounts/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('signup/', views.signup, name='signup'),
path('profile/', views.profile, name='profile'),
]
Проверка: откройте /accounts/signup/, заполните форму. После сохранения должно перекинуть на /accounts/profile/, и вы уже залогинены.
Шаг 3. Шаблоны
Django ищет шаблоны аутентификации в папке registration/. Создайте каталог templates/registration/ внутри приложения (или в общей папке шаблонов проекта).
<!-- templates/registration/login.html -->
<h1>Вход</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Войти</button>
</form>
<a href="{% url 'signup' %}">Регистрация</a>
<!-- templates/registration/signup.html -->
<h1>Регистрация</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Создать аккаунт</button>
</form>
<!-- templates/accounts/profile.html -->
<h1>Кабинет: {{ user.username }}</h1>
<p>Email: {{ user.email|default:"не указан" }}</p>
<a href="{% url 'password_change' %}">Сменить пароль</a>
<form method="post" action="{% url 'logout' %}">
{% csrf_token %}
<button type="submit">Выйти</button>
</form>
Обратите внимание: выход в Django 5.x — только POST. Ссылка <a href="/accounts/logout/"> вернёт ошибку 405. Это не баг, а защита: GET-выход можно было спровоцировать через картинку на чужом сайте.
Проверка: зайдите на /accounts/login/ — форма отрисуется. Войдите — попадёте на профиль. Кнопка «Выйти» разлогинит.
Шаг 4. Куда редиректить после входа и выхода
По умолчанию после успешного входа Django ведёт на /accounts/profile/, а без настроек после выхода — на страницу админки. Задайте адреса явно в settings.py:
# settings.py
LOGIN_REDIRECT_URL = 'profile' # имя маршрута или путь
LOGOUT_REDIRECT_URL = 'login'
LOGIN_URL = 'login' # куда кидать неавторизованных
Проверка: выйдите из аккаунта и откройте /accounts/profile/ напрямую. Должно перебросить на форму входа с параметром ?next=/accounts/profile/ в адресе. Если открылась пустая страница профиля без имени пользователя — защита не сработала, смотрите разбор ниже.
Главная ошибка новичка — не забытый шаблон, а забытый@login_required. Страница профиля без него открывается анониму и показывает пустогоuser, а по прямой ссылке на чужой ID — чужие данные.
Шаг 5. Редактирование профиля
Чтобы пользователь менял имя и email, добавьте форму на базе ModelForm. Ключевой момент — работать только с request.user, а не с объектом по ID из URL.
# accounts/forms.py
from django import forms
from django.contrib.auth.models import User
class ProfileForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
# accounts/views.py — добавить
from .forms import ProfileForm
@login_required
def profile_edit(request):
if request.method == 'POST':
# instance=request.user — правим свой профиль, не чужой
form = ProfileForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
return redirect('profile')
else:
form = ProfileForm(instance=request.user)
return render(request, 'accounts/profile_edit.html', {'form': form})
Маршрут: path('profile/edit/', views.profile_edit, name='profile_edit'). Никогда не берите пользователя как User.objects.get(pk=request.GET['id']) — это классическая дыра, когда сменой цифры в адресе редактируют чужой аккаунт.
Если не получилось
Пять ошибок, которые видят почти все:
TemplateDoesNotExist: registration/login.html— Django не нашёл шаблон. Проверьте, что папка называется именноregistration(неregistrations) и чтоAPP_DIRS: Trueстоит вTEMPLATESлибо путь добавлен вDIRS.NoReverseMatch: Reverse for 'profile' not found— в шаблоне или редиректе указано имя маршрута, которого нет вurls.py. Сверьтеname=в маршруте и строку в{% url %}.- 405 Method Not Allowed при выходе — вы сделали выход обычной ссылкой. В Django 5.x выход только через
<form method="post">с{% csrf_token %}. Forbidden (403) CSRF verification failed— в форме нет{% csrf_token %}. Добавьте тег внутрь каждой<form method="post">.- Профиль открывается без входа,
{{ user.username }}пустой — забыли декоратор@login_requiredнад вьюхой либо не задалиLOGIN_URL. Оба условия нужны, чтобы аноним улетал на форму входа.
Что делать дальше
Рабочий минимум готов. Следующие шаги, когда кабинет заработал:
- Восстановление пароля по email. Маршруты
password_resetуже подключены черезdjango.contrib.auth.urls— нужно добавить четыре шаблона и настроить отправку почты (EMAIL_BACKEND). Для локальной проверки поставьтеconsole.EmailBackend, чтобы письмо печаталось в консоль. - Расширение профиля. Дополнительные поля (аватар, телефон) не добавляйте в
User— заведите отдельную модельProfileсо связьюOneToOneFieldили, если проект новый, сразу перейдите на кастомную модель пользователя до первой миграции. - Стилизация форм.
{{ form.as_p }}— черновой вывод. Дальше подключайте пакет для рендера форм под вашу CSS-разметку или рисуйте поля вручную.
Точный список готовых маршрутов и имён вьюх аутентификации сверяйте в документации к вашей версии Django — состав между минорными версиями иногда меняется.
Разбор научной статьи: Сложный текст — понятным языком, с терминами
Спросить за 12 ₽Источники: Django 5.x — User authentication in Django, Django 5.x — Authentication Views
Частые вопросы
У меня Django 4.2, а не 5.x — код подойдёт?
Почему после входа меня кидает на страницу админки, а не на профиль?
Можно ли расширять встроенную модель User или лучше сразу делать свою?
Форма выхода возвращает 405 — что не так?
Как убедиться, что чужой пользователь не откроет мой профиль?
Куда девать пароль при редактировании профиля?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.