Spec-Zone.ru › Django 2.2

Использование системы аутентификации Django

Этот документ объясняет использование системы аутентификации Django по умолчанию. Эта конфигурация эволюционировала для удовлетворения наиболее распространенных потребностей проектов, обрабатывая широкий спектр задач и имеет продуманную реализацию паролей и разрешений. Для проектов, где потребности в аутентификации отличаются от стандартных, Django поддерживает расширенную настройку и расширение аутентификации.

Система аутентификации Django обеспечивает как аутентификацию, так и авторизацию вместе и обычно называется системой аутентификации, поскольку эти функции несколько связаны.

User объекты

User объекты являются основой системы аутентификации. Они обычно представляют людей, взаимодействующих с вашим сайтом, и используются для таких функций, как ограничение доступа, регистрация пользовательских профилей, привязка контента к создателям и т. д. В рамках фреймворка аутентификации Django существует только один класс пользователей, т. е. 'superusers' или администраторские 'staff' пользователи — это просто объекты пользователя со специальными атрибутами, а не разные классы пользовательских объектов.

Основные атрибуты пользователя по умолчанию:

  • username
  • password
  • email
  • first_name
  • last_name

См. full API documentation для полной справки, последующая документация ориентирована на выполнение задач.

Создание пользователей

Самый прямой способ создания пользователей — использование встроенной функции create_user():

>>> from django.contrib.auth.models import User
>>> user = User.objects.create_user('john', 'lennon@thebeatles.com', 'johnpassword')

# At this point, user is a User object that has already been saved
# to the database. You can continue to change its attributes
# if you want to change other fields.
>>> user.last_name = 'Lennon'
>>> user.save()

Если у вас установлен Django администратор, вы также можете создать пользователей интерактивно.

Создание суперпользователей

Создайте суперпользователей с помощью команды createsuperuser:

$ python manage.py createsuperuser --username=joe --email=joe@example.com

Вам будет предложено ввести пароль. После его ввода пользователь будет создан сразу. Если вы опустите опцию --username или --email, вам будет предложено ввести эти значения.

Изменение паролей

Django не хранит исходные (открытые) пароли в модели пользователя, а только хэш (см. документацию по управлению паролями для получения подробной информации). По этой причине не пытайтесь напрямую изменять атрибут пароля пользователя. Именно поэтому при создании пользователя используется вспомогательная функция.

Для изменения пароля пользователя у вас есть несколько вариантов:

manage.py changepassword *username* предлагает способ изменения пароля пользователя из командной строки. Вам будет предложено изменить пароль указанного пользователя, который необходимо ввести дважды. Если они совпадают, новый пароль будет изменен сразу. Если вы не укажете пользователя, команда попытается изменить пароль, имя пользователя которого совпадает с текущим системным пользователем.

Вы также можете изменить пароль программно, используя set_password():

>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='john')
>>> u.set_password('new password')
>>> u.save()

Если у вас установлен Django администратор, вы также можете изменить пароли пользователей на страницах администрирования системы аутентификации системы аутентификации.

Django также предоставляет представления и формы, которые могут использоваться для разрешения пользователям самостоятельно изменять свои пароли.

Изменение пароля пользователя приведет к выходу из системы всех их сеансов. См. Аннулирование сеанса при изменении пароля для получения подробной информации.

Авторизация пользователей

authenticate(request=None, **credentials) [source]

Используйте authenticate() для проверки набора учетных данных. Она принимает учетные данные в качестве ключевых аргументов, username и password в стандартном случае, проверяет их по отношению к каждому модулю аутентификации и возвращает объект User, если учетные данные действительны для модуля. Если учетные данные не действительны ни для одного модуля, или если модуль вызывает исключение PermissionDenied, она возвращает None. Например:

from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
if user is not None:
    # A backend authenticated the credentials
else:
    # No backend authenticated the credentials

request — это необязательный HttpRequest, который передается методу authenticate() модулей аутентификации.

Примечание

Это низкоуровневый способ проверки набора учетных данных; например, он используется в RemoteUserMiddleware. Если вы не пишете собственную систему аутентификации, вы, скорее всего, не будете использовать это. Вместо этого, если вам нужно войти в систему пользователя, используйте LoginView.

Разрешения и авторизация

Django поставляется со простой системой разрешений. Она предоставляет способ назначения разрешений конкретным пользователям и группам пользователей.

Она используется сайтом Django администратора, но вы можете использовать ее и в собственном коде.

Сайт Django администратора использует разрешения следующим образом:

  • Доступ к просмотру объектов ограничен пользователями с разрешением «просмотр» или «изменение» для данного типа объектов.
  • Доступ к просмотру формы «добавления» и добавлению объекта ограничен пользователями с разрешением «добавление» для данного типа объекта.
  • Доступ к просмотру списка изменений, просмотру формы «изменение» и изменению объекта ограничен пользователями с разрешением «изменение» для данного типа объекта.
  • Доступ к удалению объекта ограничен пользователями с разрешением «удаление» для данного типа объекта.

Разрешения могут быть заданы не только по типу объекта, но и по конкретному экземпляру объекта. Используя методы has_view_permission(), has_add_permission(), has_change_permission() и has_delete_permission(), предоставляемые классом ModelAdmin, можно настроить разрешения для различных экземпляров объектов одного типа.

User объекты имеют два поля many-to-many: groups и user_permissions. User объекты могут получать доступ к связанным объектам так же, как и любой другой Django модель:

myuser.groups.set([group_list])
myuser.groups.add(group, group, ...)
myuser.groups.remove(group, group, ...)
myuser.groups.clear()
myuser.user_permissions.set([permission_list])
myuser.user_permissions.add(permission, permission, ...)
myuser.user_permissions.remove(permission, permission, ...)
myuser.user_permissions.clear()

Стандартные разрешения

Когда django.contrib.auth указан в настройке INSTALLED_APPS, это гарантирует, что четыре стандартных разрешения — добавление, изменение, удаление и просмотр — создаются для каждой модели Django, определенной в одном из установленных приложений.

Эти разрешения будут созданы при выполнении manage.py migrate; в первый раз, когда вы запустите migrate после добавления django.contrib.auth в INSTALLED_APPS, будут созданы стандартные разрешения для всех ранее установленных моделей, а также для любых новых моделей, устанавливаемых в этот момент. В дальнейшем, он будет создавать стандартные разрешения для новых моделей каждый раз, когда вы запустите manage.py migrate (функция, создающая разрешения, связана со сигналом post_migrate).

Предполагая, что у вас есть приложение с app_label foo и моделью с именем Bar, для тестирования основных разрешений следует использовать:

  • добавить: user.has_perm('foo.add_bar')
  • изменить: user.has_perm('foo.change_bar')
  • удалить: user.has_perm('foo.delete_bar')
  • просмотреть: user.has_perm('foo.view_bar')

Модель Permission редко используется напрямую.

Группы

django.contrib.auth.models.Group — это общий способ категоризации пользователей, чтобы вы могли применять разрешения или какие-либо другие метки к этим пользователям. Пользователь может принадлежать к любому количеству групп.

Пользователь в группе автоматически обладает разрешениями, предоставленными этой группе. Например, если группа Site editors имеет разрешение can_edit_home_page, любой пользователь в этой группе будет иметь это разрешение.

Помимо разрешений, группы удобны для категоризации пользователей, чтобы присвоить им метку или расширенную функциональность. Например, вы могли бы создать группу 'Special users', и вы могли бы написать код, который, скажем, предоставил бы им доступ к закрытой части вашего сайта или отправлял им закрытые электронные письма.

Программное создание разрешений

Хотя настраиваемые разрешения могут быть определены в классе Meta модели, вы также можете создавать разрешения напрямую. Например, вы можете создать разрешение can_publish для модели BlogPost в myapp:

from myapp.models import BlogPost
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType

content_type = ContentType.objects.get_for_model(BlogPost)
permission = Permission.objects.create(
    codename='can_publish',
    name='Can Publish Posts',
    content_type=content_type,
)

Затем разрешение может быть назначено пользователю User через его атрибут user_permissions или группе Group через его атрибут permissions.

Прокси-модели нуждаются в собственном типе содержимого

Если вы хотите создать разрешения для прокси-модели, передайте for_concrete_model=False в ContentTypeManager.get_for_model(), чтобы получить соответствующий ContentType:

content_type = ContentType.objects.get_for_model(BlogPostProxy, for_concrete_model=False)
Изменено в Django 2.2:

В более старых версиях прокси-модели используют тип содержимого конкретной модели.

Кэширование разрешений

Класс ModelBackend кэширует разрешения в объекте пользователя после первого запроса для проверки разрешений. Обычно это приемлемо для цикла запроса-ответа, поскольку разрешения обычно не проверяются сразу после добавления (например, в админке). Если вы добавляете разрешения и проверяете их сразу после этого, например, в тесте или представлении, самым простым решением является повторное извлечение пользователя из базы данных. Например:

from django.contrib.auth.models import Permission, User
from django.contrib.contenttypes.models import ContentType
from django.shortcuts import get_object_or_404

from myapp.models import BlogPost

def user_gains_perms(request, user_id):
    user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
    user.has_perm('myapp.change_blogpost')

    content_type = ContentType.objects.get_for_model(BlogPost)
    permission = Permission.objects.get(
        codename='change_blogpost',
        content_type=content_type,
    )
    user.user_permissions.add(permission)

    # Checking the cached permission set
    user.has_perm('myapp.change_blogpost')  # False

    # Request new instance of User
    # Be aware that user.refresh_from_db() won't clear the cache.
    user = get_object_or_404(User, pk=user_id)

    # Permission cache is repopulated from the database
    user.has_perm('myapp.change_blogpost')  # True

    ...

Прокси-модели

Прокси-модели работают точно так же, как и конкретные модели. Разрешения создаются с помощью собственного типа содержимого прокси-модели. Прокси-модели не наследуют разрешения от конкретной модели, от которой они наследуются:

class Person(models.Model):
    class Meta:
        permissions = [('can_eat_pizzas', 'Can eat pizzas')]

class Student(Person):
    class Meta:
        proxy = True
        permissions = [('can_deliver_pizzas', 'Can deliver pizzas')]

>>> # Fetch the content type for the proxy model.
>>> content_type = ContentType.objects.get_for_model(Student, for_concrete_model=False)
>>> student_permissions = Permission.objects.filter(content_type=content_type)
>>> [p.codename for p in student_permissions]
['add_student', 'change_student', 'delete_student', 'view_student',
'can_deliver_pizzas']
>>> for permission in student_permissions:
...     user.user_permissions.add(permission)
>>> user.has_perm('app.add_person')
False
>>> user.has_perm('app.can_eat_pizzas')
False
>>> user.has_perms(('app.add_student', 'app.can_deliver_pizzas'))
True
Изменено в Django 2.2:

В более старых версиях разрешения для прокси-моделей используют тип содержимого конкретной модели, а не тип содержимого прокси-модели.

Аутентификация в веб-запросах

Django использует сессии и промежуточное ПО для подключения системы аутентификации к request objects.

Эти объекты предоставляют атрибут request.user для каждого запроса, который представляет текущего пользователя. Если текущий пользователь не авторизовался, этот атрибут будет установлен на экземпляр AnonymousUser, в противном случае он будет экземпляром User.

Вы можете отличить их с помощью is_authenticated, например:

if request.user.is_authenticated:
    # Do something for authenticated users.
    ...
else:
    # Do something for anonymous users.
    ...

Как войти в систему

Если у вас есть аутентифицированный пользователь, которого вы хотите подключить к текущей сессии — это делается с помощью функции login().

login(request, user, backend=None) [source]

Чтобы войти в систему пользователя из представления, используйте login(). Она принимает объект HttpRequest и объект User. login() сохраняет ID пользователя в сессии, используя фреймворк сессий Django.

Обратите внимание, что любые данные, заданные во время анонимной сессии, сохраняются в сессии после входа пользователя в систему.

Этот пример показывает, как вы можете использовать как authenticate(), так и login():

from django.contrib.auth import authenticate, login

def my_view(request):
    username = request.POST['username']
    password = request.POST['password']
    user = authenticate(request, username=username, password=password)
    if user is not None:
        login(request, user)
        # Redirect to a success page.
        ...
    else:
        # Return an 'invalid login' error message.
        ...

Выбор бэкэнда аутентификации

При входе пользователя в систему ID пользователя и бэкэнд, который использовался для аутентификации, сохраняются в сессии пользователя. Это позволяет одному и тому же бэкэнду аутентификации извлекать детали пользователя при последующем запросе. Бэкэнд аутентификации, который необходимо сохранить в сессии, выбирается следующим образом:

  1. Используйте значение необязательного аргумента backend, если он указан.
  2. Используйте значение атрибута user.backend, если он присутствует. Это позволяет связывать authenticate() и login(): authenticate() устанавливает атрибут user.backend в объекте пользователя, который он возвращает.
  3. Используйте значение backend в AUTHENTICATION_BACKENDS, если оно единственное.
  4. В противном случае сгенерировать исключение.

В случаях 1 и 2 значение аргумента backend или атрибута user.backend должно быть строкой импорта с точкой (как в AUTHENTICATION_BACKENDS), а не фактическим классом бэкэнда.

Как выйти из системы

logout(request) [source]

Чтобы выйти из системы пользователю, авторизованному через django.contrib.auth.login(), используйте django.contrib.auth.logout() в своём представлении. Она принимает объект HttpRequest и не возвращает значение. Пример:

from django.contrib.auth import logout

def logout_view(request):
    logout(request)
    # Redirect to a success page.

Обратите внимание, что logout() не генерирует ошибок, если пользователь не был авторизован.

При вызове logout(), данные сессии для текущего запроса полностью очищаются. Все существующие данные удаляются. Это предотвращает использование одного и того же веб-браузера другим пользователем для входа и доступа к данным сессии предыдущего пользователя. Если вы хотите добавить что-либо в сессию, что будет доступно пользователю сразу после выхода, сделайте это после вызова django.contrib.auth.logout().

Ограничение доступа для авторизованных пользователей

Прямой способ

Простой прямой способ ограничить доступ к страницам — проверить request.user.is_authenticated и либо перенаправить на страницу входа:

from django.conf import settings
from django.shortcuts import redirect

def my_view(request):
    if not request.user.is_authenticated:
        return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
    # ...

…либо отобразить сообщение об ошибке:

from django.shortcuts import render

def my_view(request):
    if not request.user.is_authenticated:
        return render(request, 'myapp/login_error.html')
    # ...

Декоратор login_required

login_required(redirect_field_name='next', login_url=None) [source]

В качестве альтернативы можно использовать удобный декоратор login_required():

from django.contrib.auth.decorators import login_required

@login_required
def my_view(request):
    ...

login_required() выполняет следующие действия:

  • Если пользователь не авторизован, перенаправляет на settings.LOGIN_URL, передавая текущий абсолютный путь в параметре запроса. Пример: /accounts/login/?next=/polls/3/.
  • Если пользователь авторизован, выполняет представление обычно. Код представления может полагаться на то, что пользователь авторизован.

По умолчанию путь, на который должен быть перенаправлен пользователь после успешной авторизации, хранится в параметре запроса с именем "next". Если вы хотите использовать другое имя для этого параметра, login_required() принимает необязательный параметр redirect_field_name.

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='my_redirect_field')
def my_view(request):
    ...

Обратите внимание, что если вы укажете значение для redirect_field_name, вам, скорее всего, также придётся настроить шаблон входа, поскольку переменная контекста шаблона, хранящая путь перенаправления, будет использовать значение redirect_field_name в качестве ключа вместо "next" (по умолчанию).

login_required() также принимает необязательный параметр login_url. Пример:

from django.contrib.auth.decorators import login_required

@login_required(login_url='/accounts/login/')
def my_view(request):
    ...

Обратите внимание, что если вы не укажете параметр login_url, вам необходимо убедиться, что settings.LOGIN_URL и ваше представление для входа должным образом связаны. Например, используя значения по умолчанию, добавьте следующие строки в свой файл URLconf:

from django.contrib.auth import views as auth_views

path('accounts/login/', auth_views.LoginView.as_view()),

Также settings.LOGIN_URL принимает имена функций представлений и именованные URL-шаблоны. Это позволяет вам свободно переопределять представление для входа в своём файле URLconf без необходимости обновления настройки.

Примечание

Декоратор login_required не проверяет флаг is_active пользователя, но по умолчанию AUTHENTICATION_BACKENDS отклоняют неактивных пользователей.

См. также

Если вы пишете пользовательские представления для админ-панели Django (или вам нужен тот же контроль доступа, что и в встроенных представлениях), вы можете найти декоратор django.contrib.admin.views.decorators.staff_member_required() полезной альтернативой login_required().

Миксин LoginRequired

При использовании представлений на основе классов, вы можете достичь того же результата, что и с login_required, используя LoginRequiredMixin. Этот миксин должен быть слева в списке наследования.

class LoginRequiredMixin

Если представление использует этот миксин, все запросы от неавторизованных пользователей будут перенаправлены на страницу входа или отобразится ошибка HTTP 403 «Запрещено», в зависимости от параметра raise_exception.

Вы можете установить любые параметры AccessMixin для настройки обработки неавторизованных пользователей:

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

Примечание

Как и декоратор login_required, этот миксин не проверяет флаг is_active пользователя, но по умолчанию AUTHENTICATION_BACKENDS отклоняют неактивных пользователей.

Ограничение доступа для авторизованных пользователей, прошедших тест

Чтобы ограничить доступ на основе определённых разрешений или другого теста, вы сделаете по существу то же, что и в предыдущем разделе.

Простой способ — выполнить ваш тест на request.user непосредственно в представлении. Например, это представление проверяет, имеет ли пользователь электронную почту в желаемом домене, и если нет, перенаправляет на страницу входа:

from django.shortcuts import redirect

def my_view(request):
    if not request.user.email.endswith('@example.com'):
        return redirect('/login/?next=%s' % request.path)
    # ...
user_passes_test(test_func, login_url=None, redirect_field_name='next') [source]

В качестве альтернативы вы можете использовать удобный декоратор user_passes_test, который выполняет перенаправление, когда вызываемая функция возвращает False:

from django.contrib.auth.decorators import user_passes_test

def email_check(user):
    return user.email.endswith('@example.com')

@user_passes_test(email_check)
def my_view(request):
    ...

user_passes_test() принимает обязательный аргумент: вызываемую функцию, которая принимает объект User и возвращает True, если пользователю разрешено просматривать страницу. Обратите внимание, что user_passes_test() не проверяет автоматически, что User не анонимный.

user_passes_test() принимает два необязательных аргумента:

login_url
Позволяет указать URL, на который будут перенаправлены пользователи, не прошедшие тест. Он может быть страницей входа и по умолчанию равен settings.LOGIN_URL, если вы не укажете его.
redirect_field_name
То же самое, что и для login_required(). Установка его в None удаляет его из URL, что может быть желательно, если вы перенаправляете пользователей, не прошедших тест, на страницу не входа, где нет параметра «следующая страница».

Например:

@user_passes_test(email_check, login_url='/login/')
def my_view(request):
    ...
class UserPassesTestMixin

При использовании классовых представлений, вы можете использовать UserPassesTestMixin для этого.

test_func()

Вы должны переопределить метод test_func() класса, чтобы предоставить тест, который будет выполняться. Кроме того, вы можете установить любые параметры AccessMixin для настройки обработки незарегистрированных пользователей:

from django.contrib.auth.mixins import UserPassesTestMixin

class MyView(UserPassesTestMixin, View):

    def test_func(self):
        return self.request.user.email.endswith('@example.com')
get_test_func()

Вы также можете переопределить метод get_test_func() для того, чтобы миксин использовал функцию с другим именем для проверок (вместо test_func()).

Использование UserPassesTestMixin

Из-за того, как реализован UserPassesTestMixin, вы не можете использовать их в списке наследования. Следующее НЕ работает:

class TestMixin1(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.email.endswith('@example.com')

class TestMixin2(UserPassesTestMixin):
    def test_func(self):
        return self.request.user.username.startswith('django')

class MyView(TestMixin1, TestMixin2, View):
    ...

Если TestMixin1 будет вызывать super() и учитывать этот результат, TestMixin1 больше не будет работать автономно.

Декоратор permission_required

permission_required(perm, login_url=None, raise_exception=False) [source]

Проверка наличия определенного разрешения у пользователя — довольно распространенная задача. По этой причине Django предоставляет сокращённый способ: декоратор permission_required().

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote')
def my_view(request):
    ...

Как и метод has_perm(), имена разрешений имеют вид "<app label>.<permission codename>" (например, polls.can_vote для разрешения на модели в приложении polls).

Декоратор также может принимать итерируемый список разрешений. В этом случае пользователь должен обладать всеми указанными разрешениями, чтобы получить доступ к представлению.

Обратите внимание, что permission_required() также принимает необязательный параметр login_url:

from django.contrib.auth.decorators import permission_required

@permission_required('polls.can_vote', login_url='/loginpage/')
def my_view(request):
    ...

Как и в декораторе login_required(), login_url по умолчанию равен settings.LOGIN_URL.

Если задан параметр raise_exception , декоратор вызовет PermissionDenied, вызвав представление 403 (HTTP Forbidden) вместо перенаправления на страницу входа в систему.

Если вы хотите использовать raise_exception , но также дать пользователям возможность сначала войти в систему, вы можете добавить декоратор login_required():

from django.contrib.auth.decorators import login_required, permission_required

@login_required
@permission_required('polls.can_vote', raise_exception=True)
def my_view(request):
    ...

Это также предотвращает цикл перенаправления, когда LoginView’s redirect_authenticated_user=True и вошедший в систему пользователь не имеет всех необходимых разрешений.

Миксин PermissionRequiredMixin

Для применения проверок разрешений к классовым представлениям, вы можете использовать PermissionRequiredMixin:

class PermissionRequiredMixin

Этот миксин, как и декоратор permission_required , проверяет, обладает ли пользователь, обращающийся к представлению, всеми указанными разрешениями. Вы должны указать разрешение (или итерируемый список разрешений) с помощью параметра permission_required:

from django.contrib.auth.mixins import PermissionRequiredMixin

class MyView(PermissionRequiredMixin, View):
    permission_required = 'polls.can_vote'
    # Or multiple of permissions:
    permission_required = ('polls.can_open', 'polls.can_edit')

Вы можете установить любые параметры AccessMixin для настройки обработки незарегистрированных пользователей.

Вы также можете переопределить эти методы:

get_permission_required()

Возвращает итерируемый список имён разрешений, используемых миксином. По умолчанию возвращает значение атрибута permission_required , преобразованное в кортеж, если это необходимо.

has_permission()

Возвращает булево значение, указывающее, обладает ли текущий пользователь разрешением на выполнение представленной функции. По умолчанию это возвращает результат вызова has_perms() со списком разрешений, возвращаемых get_permission_required().

Перенаправление неавторизованных запросов в представлениях на основе классов

Чтобы упростить обработку ограничений доступа в классовых представлениях, можно использовать AccessMixin для настройки поведения представления при отказе в доступе. Авторизованным пользователям отказывается доступ с ответом HTTP 403 Forbidden. Анонимные пользователи перенаправляются на страницу входа или получают ответ HTTP 403 Forbidden, в зависимости от атрибута raise_exception.

Изменено в Django 2.1:

В более ранних версиях, пользователи, которые были авторизованы, но не имели необходимых разрешений, перенаправлялись на страницу входа (что приводило к циклу) вместо получения ответа HTTP 403 Forbidden.

class AccessMixin
login_url

Значение по умолчанию для get_login_url(). По умолчанию равно None, в этом случае get_login_url() использует значение по умолчанию settings.LOGIN_URL.

permission_denied_message

Значение по умолчанию для get_permission_denied_message(). По умолчанию — пустая строка.

redirect_field_name

Значение по умолчанию для get_redirect_field_name(). По умолчанию "next".

raise_exception

Если этот атрибут установлен в True, при невыполнении условий будет поднято исключение PermissionDenied. При значении False (по умолчанию) анонимные пользователи перенаправляются на страницу входа.

get_login_url()

Возвращает URL, на который будут перенаправлены пользователи, не прошедшие проверку. Возвращает login_url, если оно установлено, или settings.LOGIN_URL в противном случае.

get_permission_denied_message()

Когда raise_exception равно True, этот метод может использоваться для управления сообщением об ошибке, передаваемым обработчику ошибок для отображения пользователю. По умолчанию возвращает атрибут permission_denied_message.

get_redirect_field_name()

Возвращает имя параметра запроса, который будет содержать URL, на который пользователь должен быть перенаправлен после успешного входа в систему. Если вы установите это значение в None, параметр запроса не будет добавлен. По умолчанию возвращает атрибут redirect_field_name.

handle_no_permission()

В зависимости от значения raise_exception, метод либо поднимает исключение PermissionDenied, либо перенаправляет пользователя на login_url, при необходимости включив redirect_field_name.

Отключение сессий при смене пароля

Если ваш AUTH_USER_MODEL наследуется от AbstractBaseUser или реализует свой метод get_session_auth_hash(), аутентифицированные сессии будут включать хэш, возвращаемый этой функцией. В случае AbstractBaseUser, это HMAC поля пароля. Django проверяет, что хэш в сессии для каждого запроса соответствует хэшу, вычисленному во время запроса. Это позволяет пользователю выйти из всех своих сессий, изменив свой пароль.

Включенные с Django представления по умолчанию для смены пароля, PasswordChangeView и представление user_change_password в админ-панели django.contrib.auth, обновляют сессию с новым хэшем пароля, чтобы пользователь, меняющий свой пароль, не выходил из системы. Если у вас есть пользовательское представление для смены пароля и вы хотите иметь аналогичное поведение, используйте функцию update_session_auth_hash().

update_session_auth_hash(request, user) [source]

Эта функция принимает текущий запрос и обновленный объект пользователя, из которого будет получен новый хэш сессии, и соответствующим образом обновляет хэш сессии. Она также вращает ключ сессии, так что украденный куки сессии будет недействителен.

Пример использования:

from django.contrib.auth import update_session_auth_hash

def password_change(request):
    if request.method == 'POST':
        form = PasswordChangeForm(user=request.user, data=request.POST)
        if form.is_valid():
            form.save()
            update_session_auth_hash(request, form.user)
    else:
        ...

Примечание

Так как get_session_auth_hash() основан на SECRET_KEY, обновление вашего сайта с новым секретом сделает все существующие сессии недействительными.

Встроенные представления аутентификации

Django предоставляет несколько представлений, которые вы можете использовать для обработки входа, выхода и управления паролями. Они используют стандартные формы аутентификации, но вы также можете передать свои собственные формы.

Django не предоставляет шаблон по умолчанию для представлений аутентификации. Вы должны создать свои собственные шаблоны для используемых вами представлений. Контекст шаблона документирован в каждом представлении, см. Все представления аутентификации.

Использование представлений

Существует несколько способов реализации этих представлений в вашем проекте. Самый простой способ — включить предоставленный URLconf в django.contrib.auth.urls в вашем собственном URLconf, например:

urlpatterns = [
    path('accounts/', include('django.contrib.auth.urls')),
]

Это включит следующие URL-образцы:

accounts/login/ [name='login']
accounts/logout/ [name='logout']
accounts/password_change/ [name='password_change']
accounts/password_change/done/ [name='password_change_done']
accounts/password_reset/ [name='password_reset']
accounts/password_reset/done/ [name='password_reset_done']
accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm']
accounts/reset/done/ [name='password_reset_complete']

Представления предоставляют имя URL для более удобной ссылки. Подробнее об использовании именованных URL-образцов см. в документации по URL.

Если вы хотите получить больший контроль над URL, вы можете обратиться к определенному представлению в своем URLconf:

from django.contrib.auth import views as auth_views

urlpatterns = [
    path('change-password/', auth_views.PasswordChangeView.as_view()),
]

Представления имеют необязательные аргументы, которые вы можете использовать для изменения поведения представления. Например, если вы хотите изменить имя шаблона, используемого представлением, вы можете предоставить аргумент template_name. Способ сделать это — предоставить ключевые аргументы в URLconf, которые будут переданы представлению. Например:

urlpatterns = [
    path(
        'change-password/',
        auth_views.PasswordChangeView.as_view(template_name='change-password.html'),
    ),
]

Все представления являются базированными на классах, что позволяет легко настраивать их, производя подклассы.

Все представления аутентификации

Это список всех представлений, которые django.contrib.auth предоставляет. Для реализации деталей см. Использование представлений.

END_OF_DOCUMENT_MARKER
class LoginView

Имя URL: login

Подробности использования именованных шаблонов URL см. в документации по URL.

Атрибуты:

  • template_name: Имя шаблона для отображения страницы входа в систему. По умолчанию registration/login.html.
  • redirect_field_name: Имя поля GET содержащего URL для перенаправления после входа. По умолчанию next.
  • authentication_form: Вызываемый объект (обычно класс формы) для аутентификации. По умолчанию AuthenticationForm.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым в шаблон.
  • redirect_authenticated_user: Логическая переменная, определяющая перенаправление аутентифицированных пользователей на страницу входа в систему, как если бы они только что успешно вошли в систему. По умолчанию False.

    Предупреждение

    Если вы включите redirect_authenticated_user, другие веб-сайты смогут определить, являются ли их посетители аутентифицированными на вашем сайте, запросив URL-адреса перенаправления к файлам изображений на вашем сайте. Чтобы избежать утечки информации в виде «отпечатков социальных сетей», размещайте все изображения и значок сайта на отдельном домене.

    Включение redirect_authenticated_user также может привести к циклическому перенаправлению при использовании декоратора permission_required(), если не используется параметр raise_exception.

  • success_url_allowed_hosts: set хостов, помимо request.get_host(), которые безопасны для перенаправления после входа. По умолчанию пустой set.

Вот что делает LoginView:

  • Если вызывается через GET, отображается форма входа в систему, которая отправляет POST-запрос на тот же URL. Более подробную информацию об этом вы найдете чуть ниже.
  • Если вызывается через POST с введенными пользователем учетными данными, происходит попытка входа в систему. Если вход успешен, представление перенаправляет пользователя на URL, указанный в next. Если next не указан, происходит перенаправление на settings.LOGIN_REDIRECT_URL (который по умолчанию равен /accounts/profile/). Если вход не удался, отображается форма входа в систему.

Вы сами должны предоставить html для шаблона входа в систему, который по умолчанию называется registration/login.html. Этому шаблону передаются четыре переменные контекста шаблона:

  • form: Объект Form, представляющий AuthenticationForm.
  • next: URL для перенаправления после успешного входа. Он также может содержать строку запроса.
  • site: Текущий Site в соответствии с настройкой SITE_ID. Если фреймворк сайтов не установлен, это будет экземпляр RequestSite, который определяет имя сайта и домен на основе текущего HttpRequest.
  • site_name: Псевдоним для site.name. Если фреймворк сайтов не установлен, это будет значение request.META['SERVER_NAME']. Более подробную информацию о сайтах вы найдете в фреймворке «сайты».

Если вы предпочитаете не вызывать шаблон registration/login.html, вы можете передать параметр template_name в дополнительные аргументы метода as_view в вашем URLconf. Например, эта строка URLconf использовала бы myapp/login.html вместо неё:

path('accounts/login/', auth_views.LoginView.as_view(template_name='myapp/login.html')),

Вы также можете указать имя поля GET содержащего URL для перенаправления после входа, используя redirect_field_name. По умолчанию поле называется next.

Вот пример шаблона registration/login.html в качестве отправной точки. Он предполагает, что у вас есть шаблон base.html который определяет блок content:

{% extends "base.html" %}

{% block content %}

{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}

{% if next %}
    {% if user.is_authenticated %}
    <p>Your account doesn't have access to this page. To proceed,
    please login with an account that has access.</p>
    {% else %}
    <p>Please login to see this page.</p>
    {% endif %}
{% endif %}

<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login">
<input type="hidden" name="next" value="{{ next }}">
</form>

{# Assumes you setup the password_reset view in your URLconf #}
<p><a href="{% url 'password_reset' %}">Lost password?</a></p>

{% endblock %}

Если вы настроили аутентификацию (см. Настройка аутентификации), вы можете использовать пользовательскую форму аутентификации, установив атрибут authentication_form. Эта форма должна принимать аргумент request в своем методе __init__() и предоставлять метод get_user(), который возвращает объект аутентифицированного пользователя (этот метод вызывается только после успешной проверки формы).

class LogoutView

Выводит пользователя из системы.

Имя URL: logout

Атрибуты:

  • next_page: URL для перенаправления после выхода. По умолчанию settings.LOGOUT_REDIRECT_URL.
  • template_name: Полное имя шаблона для отображения после выхода пользователя из системы. По умолчанию registration/logged_out.html.
  • redirect_field_name: Имя поля GET содержащего URL для перенаправления после выхода. По умолчанию next. Перезаписывает URL next_page, если передан параметр GET.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым в шаблон.
  • success_url_allowed_hosts: set хостов, помимо request.get_host(), которые безопасны для перенаправления после выхода. По умолчанию пустой set.

Контекст шаблона:

  • title: Строка «Выход выполнен», локализованная.
  • site: Текущий Site в соответствии с настройкой SITE_ID. Если фреймворк сайтов не установлен, это будет экземпляр RequestSite, который определяет имя сайта и домен на основе текущего HttpRequest.
  • site_name: Псевдоним для site.name. Если фреймворк сайтов не установлен, это будет значение request.META['SERVER_NAME']. Более подробную информацию о сайтах вы найдете в фреймворке «сайты».
logout_then_login(request, login_url=None)

Выводит пользователя из системы и перенаправляет на страницу входа.

Имя URL: Не указан по умолчанию

Необязательные аргументы:

  • login_url: URL страницы входа в систему для перенаправления. По умолчанию settings.LOGIN_URL, если не указано другое.
class PasswordChangeView

Имя URL: password_change

Позволяет пользователю изменить свой пароль.

Атрибуты:

  • template_name: Полное имя шаблона для отображения формы изменения пароля. По умолчанию registration/password_change_form.html.
  • success_url: URL для перенаправления после успешной смены пароля.
  • form_class: Пользовательская форма «смены пароля», которая должна принимать аргумент user. Форма отвечает за фактическое изменение пароля пользователя. По умолчанию PasswordChangeForm.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым в шаблон.

Контекст шаблона:

  • form: Форма смены пароля (см. form_class выше).
END_OF_DOCUMENT_MARKER
class PasswordChangeDoneView

Имя URL: password_change_done

Страница, отображаемая после смены пользователем пароля.

Атрибуты:

  • template_name: Полное имя шаблона для использования. По умолчанию registration/password_change_done.html, если не указано.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
class PasswordResetView

Имя URL: password_reset

Позволяет пользователю сбросить пароль, сгенерировав одноразовую ссылку для сброса пароля и отправив её на зарегистрированный адрес электронной почты.

Если указанный адрес электронной почты не существует в системе, эта функция не отправит письмо, но пользователь также не получит сообщение об ошибке. Это предотвращает утечку информации потенциальным злоумышленникам. Если вы хотите отобразить сообщение об ошибке в этом случае, вы можете создать подкласс PasswordResetForm и использовать атрибут form_class.

Пользователи, у которых пароль не используется (см. set_unusable_password()), не могут запросить сброс пароля, чтобы предотвратить злоупотребление при использовании внешнего источника аутентификации, такого как LDAP. Обратите внимание, что они не получат никакого сообщения об ошибке, поскольку это раскрыло бы существование их учетной записи, но письмо также не будет отправлено.

Атрибуты:

  • template_name: Полное имя шаблона для отображения формы сброса пароля. По умолчанию registration/password_reset_form.html, если не указано.
  • form_class: Форма, которая будет использоваться для получения адреса электронной почты пользователя для сброса пароля. По умолчанию PasswordResetForm.
  • email_template_name: Полное имя шаблона для создания письма со ссылкой на сброс пароля. По умолчанию registration/password_reset_email.html, если не указано.
  • subject_template_name: Полное имя шаблона для темы письма со ссылкой на сброс пароля. По умолчанию registration/password_reset_subject.txt, если не указано.
  • token_generator: Экземпляр класса для проверки одноразовой ссылки. По умолчанию default_token_generator, это экземпляр django.contrib.auth.tokens.PasswordResetTokenGenerator.
  • success_url: URL для перенаправления после успешного запроса сброса пароля.
  • from_email: Действительный адрес электронной почты. По умолчанию Django использует DEFAULT_FROM_EMAIL.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
  • html_email_template_name: Полное имя шаблона для создания письма multipart со ссылкой на сброс пароля. По умолчанию письмо HTML не отправляется.
  • extra_email_context: Словарь данных контекста, доступных в шаблоне письма. Он может использоваться для переопределения стандартных значений контекста шаблона, например, domain.

Контекст шаблона:

  • form: Форма (см. form_class выше) для сброса пароля пользователя.

Контекст шаблона письма:

  • email: Псевдоним для user.email
  • user: Текущий User в соответствии с полем формы email. Только активные пользователи могут сбросить свои пароли (User.is_active is True).
  • site_name: Псевдоним для site.name. Если у вас не установлен фреймворк сайта, это будет установлено в значение request.META['SERVER_NAME']. Подробнее о сайтах см. Фреймворк «sites».
  • domain: Псевдоним для site.domain. Если у вас не установлен фреймворк сайта, это будет установлено в значение request.get_host().
  • protocol: http или https
  • uid: Первичный ключ пользователя, закодированный в base 64.
  • token: Токен для проверки того, что ссылка на сброс пароля действительна.

Пример registration/password_reset_email.html (шаблон тела письма):

Someone asked for password reset for email {{ email }}. Follow the link below:
{{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}

Один и тот же контекст шаблона используется для шаблона темы. Тема должна быть строкой простого текста в одну строку.

class PasswordResetDoneView

Имя URL: password_reset_done

Страница, отображаемая после отправки пользователю ссылки для сброса пароля. Эта функция вызывается по умолчанию, если PasswordResetView не имеет явно заданного URL success_url.

Примечание

Если предоставленный адрес электронной почты не существует в системе, пользователь неактивен или у него неиспользуемый пароль, пользователь все равно будет перенаправлен на эту страницу, но письмо не будет отправлено.

Атрибуты:

  • template_name: Полное имя шаблона для использования. По умолчанию registration/password_reset_done.html, если не указано.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.
class PasswordResetConfirmView

Имя URL: password_reset_confirm

Отображает форму для ввода нового пароля.

Ключевые аргументы из URL:

  • uidb64: Идентификатор пользователя, закодированный в base 64.
  • token: Токен для проверки, что пароль действителен.

Атрибуты:

  • template_name: Полное имя шаблона для отображения страницы подтверждения пароля. Значение по умолчанию registration/password_reset_confirm.html.
  • token_generator: Экземпляр класса для проверки пароля. По умолчанию default_token_generator, это экземпляр django.contrib.auth.tokens.PasswordResetTokenGenerator.
  • post_reset_login: Логическое значение, указывающее, следует ли автоматически аутентифицировать пользователя после успешного сброса пароля. По умолчанию False.
  • post_reset_login_backend: Точка доступа к аутентификационному бэкенду для использования при аутентификации пользователя, если post_reset_login True . Требуется только если у вас настроено несколько AUTHENTICATION_BACKENDS. По умолчанию None.
  • form_class: Форма, которая будет использоваться для установки пароля. По умолчанию SetPasswordForm.
  • success_url: URL для перенаправления после завершения сброса пароля. По умолчанию 'password_reset_complete'.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.

Контекст шаблона:

  • form: Форма (см. form_class выше) для установки нового пароля пользователя.
  • validlink: Логическое значение, True, если ссылка (комбинация uidb64 и token) действительна или еще не использовалась.
class PasswordResetCompleteView

Имя URL: password_reset_complete

Отображает представление, информирующее пользователя о том, что пароль успешно изменен.

Атрибуты:

  • template_name: Полное имя шаблона для отображения представления. По умолчанию registration/password_reset_complete.html.
  • extra_context: Словарь данных контекста, который будет добавлен к стандартным данным контекста, передаваемым шаблону.

Вспомогательные функции

redirect_to_login(next, login_url=None, redirect_field_name='next')

Перенаправляет на страницу входа в систему, а затем обратно на другой URL после успешного входа в систему.

Обязательные аргументы:

  • next: URL для перенаправления после успешного входа в систему.

Необязательные аргументы:

  • login_url: URL страницы входа в систему для перенаправления. По умолчанию settings.LOGIN_URL, если не указано.
  • redirect_field_name: Имя поля GET содержащего URL для перенаправления после выхода из системы. Переопределяет next если указан параметр GET.

Встроенные формы

Если вы не хотите использовать встроенные представления, но хотите удобство не писать формы для этой функциональности, система аутентификации предоставляет несколько встроенных форм, расположенных в django.contrib.auth.forms:

Примечание

Встроенные формы аутентификации делают определенные предположения о модели пользователя, с которой они работают. Если вы используете пользовательскую модель, возможно, необходимо определить собственные формы для системы аутентификации. Дополнительную информацию см. в документации по использованию встроенных форм аутентификации с пользовательскими моделями.

class AdminPasswordChangeForm

Форма, используемая в админском интерфейсе для смены пароля пользователя.

Принимает user в качестве первого позиционного аргумента.

class AuthenticationForm

Форма для входа пользователя.

Принимает request в качестве первого позиционного аргумента, который хранится в экземпляре формы для использования дочерними классами.

confirm_login_allowed(user)

По умолчанию AuthenticationForm отклоняет пользователей, у которых флаг is_active установлен в False. Вы можете переопределить это поведение с помощью пользовательской политики, определяющей, какие пользователи могут войти. Сделайте это с помощью пользовательской формы, которая расширяет AuthenticationForm и переопределяет метод confirm_login_allowed(). Этот метод должен вызывать исключение ValidationError, если данному пользователю запрещён вход.

Например, чтобы разрешить вход всем пользователям независимо от статуса «активный»:

from django.contrib.auth.forms import AuthenticationForm

class AuthenticationFormWithInactiveUsersOkay(AuthenticationForm):
    def confirm_login_allowed(self, user):
        pass

(В этом случае вам также необходимо использовать механизм аутентификации, который допускает неактивных пользователей, например, AllowAllUsersModelBackend.)

Или, чтобы разрешить вход только некоторым активным пользователям:

class PickyAuthenticationForm(AuthenticationForm):
    def confirm_login_allowed(self, user):
        if not user.is_active:
            raise forms.ValidationError(
                _("This account is inactive."),
                code='inactive',
            )
        if user.username.startswith('b'):
            raise forms.ValidationError(
                _("Sorry, accounts starting with 'b' aren't welcome here."),
                code='no_b_users',
            )
class PasswordChangeForm

Форма, позволяющая пользователю изменить свой пароль.

class PasswordResetForm

Форма для генерации и отправки по электронной почте одноразовой ссылки для сброса пароля пользователя.

send_mail(subject_template_name, email_template_name, context, from_email, to_email, html_email_template_name=None)

Использует аргументы для отправки EmailMultiAlternatives. Можно переопределить, чтобы настроить, как отправлять электронное письмо пользователю.

Параметры:
  • subject_template_name – шаблон для темы.
  • email_template_name – шаблон для тела письма.
  • context – контекст, передаваемый в subject_template, email_template, и html_email_template (если он не None).
  • from_email – электронный адрес отправителя.
  • to_email – электронный адрес запрашивающего.
  • html_email_template_name – шаблон для HTML-тела; по умолчанию None, в этом случае отправляется обычное текстовое письмо.

По умолчанию save() заполняет context теми же переменными, которые PasswordResetView передает в контекст своего письма.

class SetPasswordForm

Форма, позволяющая пользователю изменить пароль без ввода старого пароля.

class UserChangeForm

Форма, используемая в админском интерфейсе для изменения информации и разрешений пользователя.

class UserCreationForm

ModelForm для создания нового пользователя.

Она имеет три поля: username (из модели пользователя), password1, и password2. Она проверяет, что password1 и password2 совпадают, проверяет пароль с помощью validate_password() и устанавливает пароль пользователя с помощью set_password().

Данные аутентификации в шаблонах

Текущий вошедший пользователь и его разрешения доступны в контексте шаблона, когда вы используете RequestContext.

Техническая информация

Технически, эти переменные доступны в контексте шаблона только если вы используете RequestContext и включён процессор контекста 'django.contrib.auth.context_processors.auth'. Он есть в файле настроек по умолчанию. Для более подробной информации см. документацию по RequestContext.

Пользователи

При рендеринге шаблона RequestContext, текущий вошедший пользователь, либо экземпляр User, либо экземпляр AnonymousUser, хранится в переменной шаблона {{ user }}:

{% if user.is_authenticated %}
    <p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
    <p>Welcome, new user. Please log in.</p>
{% endif %}

Эта переменная контекста шаблона недоступна, если не используется RequestContext.

Разрешения

Разрешения текущего вошедшего пользователя хранятся в переменной шаблона {{ perms }}. Это экземпляр django.contrib.auth.context_processors.PermWrapper, который является шаблоно-совместимым прокси-сервером для разрешений.

Вычисление одноатрибутного поиска {{ perms }} в качестве булевого значения — это прокси для User.has_module_perms(). Например, чтобы проверить, имеет ли вошедший пользователь какие-либо разрешения в приложении foo:

{% if perms.foo %}

Вычисление двухъуровневого атрибутного поиска в качестве булевого значения — это прокси для User.has_perm(). Например, чтобы проверить, имеет ли вошедший пользователь разрешение foo.can_vote:

{% if perms.foo.can_vote %}

Вот более полный пример проверки разрешений в шаблоне:

{% if perms.foo %}
    <p>You have permission to do something in the foo app.</p>
    {% if perms.foo.can_vote %}
        <p>You can vote!</p>
    {% endif %}
    {% if perms.foo.can_drive %}
        <p>You can drive!</p>
    {% endif %}
{% else %}
    <p>You don't have permission to do anything in the foo app.</p>
{% endif %}

Возможно также использовать поиск разрешений с помощью {% if in %} операторов. Например:

{% if 'foo' in perms %}
    {% if 'foo.can_vote' in perms %}
        <p>In lookup works, too.</p>
    {% endif %}
{% endif %}

Управление пользователями в админке

При установке django.contrib.admin и django.contrib.auth, админка предоставляет удобный способ просмотра и управления пользователями, группами и разрешениями. Пользователи могут создаваться и удаляться как любые модели Django. Группы могут создаваться, а разрешения могут назначаться пользователям или группам. Журнал изменений, вносимых пользователями в модели через админку, также хранится и отображается.

Создание пользователей

Вы должны увидеть ссылку «Пользователи» в разделе «Auth» на главной странице админки. Страница админки «Добавить пользователя» отличается от стандартных страниц админки тем, что она требует выбора имени пользователя и пароля, прежде чем вы сможете отредактировать другие поля пользователя.

Также обратите внимание: если вы хотите, чтобы учётная запись пользователя могла создавать пользователей с помощью сайта админки Django, вам необходимо предоставить ей разрешение на добавление пользователей и изменение пользователей (т.е., разрешения «Добавить пользователя» и «Изменить пользователя»). Если учётная запись имеет разрешение на добавление пользователей, но не на изменение, она не сможет добавлять пользователей. Почему? Потому что, если вы имеете разрешение на добавление пользователей, вы можете создать суперпользователей, которые, в свою очередь, могут изменить других пользователей. Поэтому Django требует разрешения на добавление и изменение как меру безопасности.

Внимательно подходите к тому, как вы предоставляете пользователям возможность управления разрешениями. Если вы даёте не суперпользователю возможность редактировать пользователей, это в конечном счёте то же самое, что дать ему статус суперпользователя, потому что он сможет повысить права пользователей, включая себя!

Изменение паролей

Пароли пользователей не отображаются в админке (и не хранятся в базе данных), но данные о хранении паролей отображаются. В отображении этой информации содержится ссылка на форму изменения пароля, которая позволяет администраторам изменять пароли пользователей.

© Django Software Foundation and individual contributors
Licensed under the BSD License.
https://docs.djangoproject.com/en/2.2/topics/auth/default/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API