Перейти к содержимому

Get user model django что это

  • автор:

Пользовательская модель User

Каждый новый проект Django должен использовать пользовательскую модель User. Официальная документация Django гласит, что это «настоятельно рекомендуется», но я сделаю еще один шаг и без колебаний скажу: вы просто с ума сошли, если не использовали пользовательскую модель раньше.

Зачем? Потому что вам придется внести изменения в пользователя в какой-то момент в жизни вашего проекта — добавить поле даты рождения, возраст, что угодно — и если вы не начали с пользовательской модели User до самой первой выполненной вами команды переноса, тогда вы попадете в мир боли.

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

Можно ли переключиться на пользовательскую модель в середине проекта? Да. Хочешь ли ты это сделать? Лучше не делать.

Вот самый простой способ, чтобы начать каждый новый проект с правильного пути.

Шаг 1. Создание нового проекта

В командной строке перейдите в новый каталог для своих проектов, используйте Pipenv для установки Django, активируйте виртуальную среду и создайте новый проект с именем new_project . Давайте предположим, что мы хотим использовать папку code в Desktop , так пример на Mac.

$ cd ~/Desktop $ mkdir code && cd code $ pipenv install django $ pipenv shell (code) $ django-admin startproject new_project . 

Теперь нам нужно создать приложение пользователя, а затем обновить 4 файла. Готовы?

Шаг 2. Создание приложения пользователя

(code) $ python manage.py startapp users 

Теперь давайте расскажем Django о новом приложении и обновим AUTH_USER_MODEL , чтобы Django знал, что нужно использовать нашу новую модель CustomUser вместо модели User по умолчанию.

Откройте new_project/settings.py в текстовом редакторе и внесите следующие два изменения:

# new_project/settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # Local 'users.apps.UsersConfig', # новое ] . AUTH_USER_MODEL = 'users.CustomUser' # новое 

Шаг 3. Модель CustomUser

Мы хотим расширить (или скопировать) существующую модель User и назвать ее как-то иначе, в нашем случае CustomUser . Это все, что нам нужно сделать. Просто сделайте копию, и тогда мы сможем настроить ее так, как нам нравится, но при этом использовать все преимущества встроенного User .

Нам даже не нужно добавлять поле на этом этапе!

# users/models.py from django.contrib.auth.models import AbstractUser from django.db import models class CustomUser(AbstractUser): pass # add additional fields in here 

Шаг 4: Обновление форм

Django использует модель User — теперь нашу модель CustomUser , поскольку мы указали ее в AUTH_USER_MODEL повсюду. Два основных места — это когда создается новый пользователь и когда мы что-то меняем у пользователя. Поэтому мы должны снова расширить встроенные формы для этого и указать их для нашей новой модели CustomUser .

Создайте новый файл users/forms.py и заполните его следующим текстом:

# users/forms.py from django import forms from django.contrib.auth.forms import UserCreationForm, UserChangeForm from .models import CustomUser class CustomUserCreationForm(UserCreationForm): class Meta(UserCreationForm): model = CustomUser fields = ('username', 'email') class CustomUserChangeForm(UserChangeForm): class Meta: model = CustomUser fields = ('username', 'email') 

Шаг 5: Обновление admin.py

Модель Django User тесно связана с превосходным встроенным приложением администратора admin , поэтому мы должны указать Django использовать вместо этого CustomUser . Вот как:

# users/admin.py from django.contrib import admin from django.contrib.auth import get_user_model from django.contrib.auth.admin import UserAdmin from .forms import CustomUserCreationForm, CustomUserChangeForm from .models import CustomUser class CustomUserAdmin(UserAdmin): add_form = CustomUserCreationForm form = CustomUserChangeForm model = CustomUser list_display = ['email', 'username',] admin.site.register(CustomUser, CustomUserAdmin) 

Всё.

И это все. Создайте файл миграции для наших изменений, а затем впервые запустите миграцию, чтобы инициализировать нашу базу данных с помощью CustomUser вместо User .

(code) $ python manage.py makemigrations users (code) $ python manage.py migrate 

Поздравляем! Ваш проект Django рассчитан на будущее и вы можете продолжить работу без проблем.

Создание пользовательской модели User в Django

Как полностью заменить поле имени пользователя на поле электронной почты для аутентификации в Django?

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

  1. Замена пользовательской модели пользователя руководство из официальной документации Django
  2. Переход на пользовательскую модель пользователя в Django статья в блоге

Цели

К концу этой статьи вы должны уметь:

  1. Опишите разницу между AbstractUser и AbstractBaseUser
  2. Объясните, почему вам следует настроить собственную модель пользователя при запуске нового проекта Django.
  3. Запустите новый проект Django с пользовательской моделью пользователя.
  4. Используйте адрес электронной почты в качестве основного идентификатора пользователя вместо имени пользователя для аутентификации.
  5. Практика тестирования — первая разработка при реализации пользовательской модели пользователя.

AbstractUser или AbstractBaseUser

По умолчанию модель User в Django использует имя пользователя для уникальной идентификации пользователя при аутентификации. Если вы предпочитаете использовать адрес электронной почты, вам необходимо создать пользовательскую модель User, используя подкласс AbstractUser или AbstractBaseUser .

  1. AbstractUser : Используйте этот вариант, если вас устраивают существующие поля в модели User и вы просто хотите удалить поле имени пользователя.
  2. AbstractBaseUser : Используйте эту опцию, если вы хотите начать с нуля, создав свою собственную, совершенно новую модель User.

В этом посте мы рассмотрим оба варианта: AbstractUser и AbstractBaseUser .

Шаги для каждого из них одинаковы:

  1. Создайте собственную модель пользователя и менеджера.
  2. Обновите settings.py
  3. Настроить формы UserCreationForm и UserChangeForm
  4. Обновите админку

Начиная новый проект Django, настоятельно рекомендуется установить пользовательскую модель User. Без нее вам придется создать другую модель (например, UserProfile ) и связать ее с моделью Django User с помощью OneToOneField , если вы хотите добавить новые поля в модель User.

Настройка проекта

Начните с создания нового проекта Django вместе с пользовательским приложением:

$ mkdir django-custom-user-model && cd django-custom-user-model $ python3 -m venv env $ source env/bin/activate (env)$ pip install Django==3.2.2 (env)$ django-admin startproject hello_django . (env)$ python manage.py startapp users 

НЕ применяйте миграции. Помните: вы должны создать пользовательскую модель User до применения первой миграции.

Добавьте новое приложение в список INSTALLED_APPS в settings.py:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'users', ] 

Тесты

Давайте воспользуемся подходом, основанным на тестировании:

from django.contrib.auth import get_user_model from django.test import TestCase class UsersManagersTests(TestCase): def test_create_user(self): User = get_user_model() user = User.objects.create_user(email='normal@user.com', password='foo') self.assertEqual(user.email, 'normal@user.com') self.assertTrue(user.is_active) self.assertFalse(user.is_staff) self.assertFalse(user.is_superuser) try: # username is None for the AbstractUser option # username does not exist for the AbstractBaseUser option self.assertIsNone(user.username) except AttributeError: pass with self.assertRaises(TypeError): User.objects.create_user() with self.assertRaises(TypeError): User.objects.create_user(email='') with self.assertRaises(ValueError): User.objects.create_user(email='', password="foo") def test_create_superuser(self): User = get_user_model() admin_user = User.objects.create_superuser(email='super@user.com', password='foo') self.assertEqual(admin_user.email, 'super@user.com') self.assertTrue(admin_user.is_active) self.assertTrue(admin_user.is_staff) self.assertTrue(admin_user.is_superuser) try: # username is None for the AbstractUser option # username does not exist for the AbstractBaseUser option self.assertIsNone(admin_user.username) except AttributeError: pass with self.assertRaises(ValueError): User.objects.create_superuser( email='super@user.com', password='foo', is_superuser=False) 

Добавьте спецификации в файл users/tests.py, а затем убедитесь, что тесты не работают.

Менеджер моделей

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

Создайте файл manager.py в папке «users» каталог:

from django.contrib.auth.base_user import BaseUserManager from django.utils.translation import ugettext_lazy as _ class CustomUserManager(BaseUserManager): """ Custom user model manager where email is the unique identifiers for authentication instead of usernames. """ def create_user(self, email, password, **extra_fields): """ Create and save a User with the given email and password. """ if not email: raise ValueError(_('The Email must be set')) email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save() return user def create_superuser(self, email, password, **extra_fields): """ Create and save a SuperUser with the given email and password. """ extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_active', 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) 

Модель пользователя

Решите, какой вариант вы хотите использовать: создание подкласса от AbstractUser или AbstractBaseUser .

AbstractUser

from django.contrib.auth.models import AbstractUser from django.db import models from django.utils.translation import ugettext_lazy as _ from .managers import CustomUserManager class CustomUser(AbstractUser): username = None email = models.EmailField(_('email address'), unique=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] objects = CustomUserManager() def __str__(self): return self.email 
  1. Создан новый класс CustomUser , который является подклассом AbstractUser .
  2. Удалено поле имени пользователя
  3. Сделал поле электронной почты обязательным и уникальным
  4. Установлен USERNAME_FIELD — который определяет уникальный идентификатор для модели пользователя — на электронную почту
  5. Указано, что все объекты для класса поступают из CustomUserManager

AbstractBaseUser

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.db import models from django.utils import timezone from django.utils.translation import gettext_lazy as _ from .managers import CustomUserManager class CustomUser(AbstractBaseUser, PermissionsMixin): email = models.EmailField(_('email address'), unique=True) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) date_joined = models.DateTimeField(default=timezone.now) USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] objects = CustomUserManager() def __str__(self): return self.email 
  1. Создан новый класс CustomUser , который является подклассом AbstractBaseUser.
  2. Добавлены поля для электронной почты, is_staff , is_active и date_joined .
  3. Установлен USERNAME_FIELD — который определяет уникальный идентификатор для модели пользователя — на электронную почту
  4. Указано, что все объекты для класса поступают из CustomUserManager

Настройки

Добавьте следующую строку в файл settings.py, чтобы Django знал, как использовать новый класс User :

AUTH_USER_MODEL = 'users.CustomUser' 

Теперь можно создать и применить миграцию, которая создаст новую базу данных, использующую пользовательскую модель User. Прежде чем мы это сделаем, давайте посмотрим, как будет выглядеть миграция без создания файла миграции, с флагом —dry-run:

(env)$ python manage.py makemigrations --dry-run --verbosity 3 

Вы должны увидеть что-то похожее на:

# Generated by Django 3.2.2 on 2021-05-12 20:43 from django.db import migrations, models import django.utils.timezone class Migration(migrations.Migration): initial = True dependencies = [ ('auth', '0012_alter_user_first_name_max_length'), ] operations = [ migrations.CreateModel( name='CustomUser', 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')), ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), ('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')), ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')), ('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, >, ), ] 

Если вы пошли по маршруту AbstractBaseUser , у вас не будет полей для first_name или last_name . Почему?

Убедитесь, что миграция не включает поле имени пользователя. Затем создайте и примените миграцию:

(env)$ python manage.py makemigrations (env)$ python manage.py migrate 
$ sqlite3 db.sqlite3 SQLite version 3.28.0 2019-04-15 14:49:49 Enter ".help" for usage hints. sqlite> .tables auth_group django_migrations auth_group_permissions django_session auth_permission users_customuser django_admin_log users_customuser_groups django_content_type users_customuser_user_permissions sqlite> .schema users_customuser CREATE TABLE IF NOT EXISTS "users_customuser" ( "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "password" varchar(128) NOT NULL, "last_login" datetime NULL, "is_superuser" bool NOT NULL, "first_name" varchar(150) NOT NULL, "last_name" varchar(150) NOT NULL, "is_staff" bool NOT NULL, "is_active" bool NOT NULL, "date_joined" datetime NOT NULL, "email" varchar(254) NOT NULL UNIQUE ); 

Если вы пошли по маршруту AbstractBaseUser , почему last_login является частью модели?

Вы можете ссылаться на модель User либо с помощью get_user_model() , либо с помощью settings.AUTH_USER_MODEL . Дополнительная информация приведена в Руководство модели пользователя из официальной документации.

Также, когда вы создаете суперпользователя, вам должно быть предложено ввести email, а не имя пользователя:

(env)$ python manage.py createsuperuser Email address: test@test.com Password: Password (again): Superuser created successfully. 

Убедитесь, что тесты пройдены:

(env)$ python manage.py test Creating test database for alias 'default'. System check identified no issues (0 silenced). .. ---------------------------------------------------------------------- Ran 2 tests in 0.282s OK Destroying test database for alias 'default'. 

Формы

Затем давайте создадим подкласс форм UserCreationForm и UserChangeForm , чтобы они использовали новую модель CustomUser .

Создайте в «users» новый файл с именем forms.py:

from django.contrib.auth.forms import UserCreationForm, UserChangeForm from .models import CustomUser class CustomUserCreationForm(UserCreationForm): class Meta: model = CustomUser fields = ('email',) class CustomUserChangeForm(UserChangeForm): class Meta: model = CustomUser fields = ('email',) 

Админ

Скажите админке использовать эти формы, создав подкласс UserAdmin в users/admin.py:

from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .forms import CustomUserCreationForm, CustomUserChangeForm from .models import CustomUser class CustomUserAdmin(UserAdmin): add_form = CustomUserCreationForm form = CustomUserChangeForm model = CustomUser list_display = ('email', 'is_staff', 'is_active',) list_filter = ('email', 'is_staff', 'is_active',) fieldsets = ( (None, ), ('Permissions', ), ) add_fieldsets = ( (None, < 'classes': ('wide',), 'fields': ('email', 'password1', 'password2', 'is_staff', 'is_active')>), ) search_fields = ('email',) ordering = ('email',) admin.site.register(CustomUser, CustomUserAdmin) 

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

django admin

Заключение

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

Вы можете найти окончательный код для обоих вариантов, AbstractUser и AbstractBaseUser , в репозитории django-custom-user-model. Последние примеры кода включают шаблоны, представления и URL, необходимые для аутентификации пользователя.

Руководство Django Часть 8: Аутентификация и авторизация пользователя

В данном руководстве мы продемонстрируем вам систему входа пользователя на ваш сайт используя его собственный аккаунт. Кроме того, мы покажем как реализовать контроль того, что может видеть и делать пользователь, в зависимости от того, залогинен он, или нет, а также имеет ли он соответствующий уровень прав доступа (permissions). Для того чтобы продемонстрировать все это, мы расширим LocalLibrary, добавив страницы для входа/выхода, а также страницы просмотра/редактирования книг, специфические для пользователя и персонала.

Требования: Завершить изучение предыдущих тем руководства, включая Руководство Django Часть 7: Работа с сессиями.
Цель: Понимать как настроить и использовать механизм аутентификации пользователя и разграничений прав доступа.

Обзор

Django предоставляет систему аутентификации и авторизации («permission») пользователя, реализованную на основе фреймворка работы с сессиями, который мы рассматривали в предыдущей части. Система аутентификации и авторизации позволяет вам проверять учётные данные пользователей и определять какие действия какой пользователь может выполнять. Данный фреймворк включает в себя встроенные модели для Пользователей и Групп (основной способ применения прав доступа для более чем одного пользователя), непосредственно саму систему прав доступа (permissions)/флаги, которые определяют может ли пользователь выполнить задачу, с какой формой и отображением для авторизованных пользователей, а так же получить доступ к контенту с ограниченным доступом.

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

В данном разделе руководства мы покажем вам реализацию аутентификации пользователя на сайте LocalLibrary, создание страниц входа/выхода, добавления разграничения доступа (permissions) к вашим моделям, а также продемонстрируем контроль за доступом к некоторым страницам. Мы будем использовать аутентификацию/авторизацию для показа пользователям и сотрудникам библиотеки, списков книг, которые были взяты на прокат.

Система аутентификации является очень гибкой и позволяет вам формировать свои собственные URL-адреса, формы, отображения, а также шаблоны страниц, если вы пожелаете, с нуля, через простой вызов функций соответствующего API для авторизации пользователя. Тем не менее, в данной статье мы будем использовать «встроенные» в Django методы отображений и форм аутентификации, а также методы построения страниц входа и выхода. Нам все ещё необходимо создавать шаблоны страниц, но это будет достаточно несложно.

Мы покажем вам как реализовать разграничение доступа (permissions), а также выполнять соответствующую проверку статусов авторизации и прав доступа, в отображениях, и в шаблонах страниц.

Подключение аутентификации

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

Примечание: Необходимые настройки были выполнены для нас, когда мы создали приложение при помощи команды django-admin startproject . Таблицы базы данных для пользователей и модели авторизации были созданы, когда в первый раз выполнили команду python manage.py migrate .

Соответствующие настройки сделаны в параметрах INSTALLED_APPS и MIDDLEWARE файла проекта (locallibrary/locallibrary/settings.py), как показано ниже:

= [ ... 'django.contrib.auth', # Фреймворк аутентификации и моделей по умолчанию. 'django.contrib.contenttypes', # Django контент-типовая система (даёт разрешения, связанные с моделями). .... MIDDLEWARE = [ ... 'django.contrib.sessions.middleware.SessionMiddleware', # Управление сессиями между запросами ... 'django.contrib.auth.middleware.AuthenticationMiddleware', # Связывает пользователей, использующих сессии, запросами. .... 

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

Вы уже создали своего первого пользователя когда мы рассматривали Административная панель сайта Django в части 4 (это был суперпользователь, созданный при помощи команды python manage.py createsuperuser ). Наш суперпользователь уже авторизован и имеет все необходимые уровни доступа к данным и функциям, таким образом нам необходимо создать тестового пользователя для отработки соответствующей работы сайта. В качестве наиболее быстрого способа, мы будем использовать административную панель сайта для создания соответствующих групп и аккаунтов locallibrary.

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

from django.contrib.auth.models import User # Создайте пользователя и сохраните его в базе данных user = User.objects.create_user('myusername', 'myemail@crazymail.com', 'mypassword') # Обновите поля и сохраните их снова user.first_name = 'John' user.last_name = 'Citizen' user.save() 

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

Запустите сервер разработки и перейдите к административной панели вашего сайта ( http://127.0.0.1:8000/admin/ ). Залогиньтесь на сайте при помощи параметров (имя пользователя и пароля) аккаунта суперпользователя. Самая «верхняя» страница панели Администратора показывает все наши модели. Для того, чтобы увидеть записи в разделе Authentication and Authorisation вы можете нажать на ссылку Users, или Groups.

Admin site - add groups or users

В первую очередь, в качестве нового члена нашего сайта, давайте создадим новую группу.

Admin site - add group

  1. Нажмите на кнопку Add(Добавить) (рядом с Group) и создайте новую группу; для данной группы введите Name (Имя) «Library Members».
  2. Для данной группы не нужны какие-либо разрешения, поэтому мы просто нажимаем кнопку SAVE (Сохранить) (вы перейдёте к списку групп).

Теперь давайте создадим пользователя:

  1. Перейдите обратно на домашнюю страницу административной панели
  2. Для перехода к диалогу добавления пользователя нажмите на кнопку Add, соответствующую строке Users (Пользователи). Admin site - add user pt1
  3. Введите соответствующие Username (имя пользователя) и Password/Password confirmation (пароль/подтверждение пароля) для вашего тестового пользователя
  4. Нажмите SAVE для завершения процесса создания пользователя. Административная часть сайта создаст нового пользователя и немедленно перенаправит вас на страницу Change user (Изменение параметров пользователя) где вы можете, соответственно, изменить ваш username, а кроме того добавить информацию для дополнительных полей модели User. Эти поля включают в себя имя пользователя, фамилию, адрес электронной почты, статус пользователя, а также соответствующие параметры доступа (может быть установлен только флаг Active). Ниже вы можете определить группу для пользователя и необходимые параметры доступа, а кроме того, вы можете увидеть важные даты, относящиеся к пользователю (дату подключения к сайту и дату последнего входа). Admin site - add user pt2
  5. В разделе Groups, из списка Доступные группы выберите группу Library Member, а затем переместите её в блок «Выбранные группы» (нажмите стрелку-«направо», находящуюся между блоками). Admin site - add user to group
  6. Больше нам не нужно здесь нечего делать, просто нажмите «Save»(Сохранить), и вы вернётесь к списку созданных пользователей.

Вот и все! Теперь у вас есть учётная запись «обычного члена библиотеки», которую вы сможете использовать для тестирования (как только добавим страницы, чтобы пользователи могли войти в систему).

Примечание: Попробуйте создать другого пользователя, например «Библиотекаря». Так же создайте группу «Библиотекарей» и добавьте туда своего только что созданного библиотекаря

Настройка представлений проверки

Django предоставляет почти все, что нужно для создания страниц аутентификации входа, выхода из системы и управления паролями из коробки. Это включает в себя url-адреса, представления (views) и формы,но не включает шаблоны — мы должны создать свой собственный шаблон!

В этом разделе мы покажем, как интегрировать систему по умолчанию в Сайт LocalLibrary и создать шаблоны. Мы поместим их в основные URL проекта.

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

**Примечание:**В этом случае мы могли бы разумно поместить страницы аутентификации, включая URL-адреса и шаблоны, в наше приложение каталога. Однако, если бы у нас было несколько приложений, было бы лучше отделить это общее поведение входа в систему и иметь его доступным на всем сайте, так что это то, что мы показали здесь!

Проектирование URLs

Добавьте следующее в нижней части проекта urls.py файл (locallibrary/locallibrary/urls.py) файл:

#Add Django site authentication urls (for login, logout, password management) urlpatterns += [ path('accounts/', include('django.contrib.auth.urls')), ] 

Перейдите по http://127.0.0.1:8000/accounts/ URL (обратите внимание на косую черту!), Django покажет ошибку, что он не смог найти этот URL, и перечислить все URL, которые он пытался открыть. Из этого вы можете увидеть URL-адреса, которые будут работать, например:

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

Примечание:

/ 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-адресу входа ( http://127.0.0.1:8000/accounts/login/ ). Это приведёт к сбою снова, но с ошибкой, сообщающей вам, что нам не хватает требуемого шаблона (registration / login.html) в пути поиска шаблона. Вы увидите следующие строки, перечисленные в жёлтом разделе вверху:

: TemplateDoesNotExist Exception Value: registration/login.html 

Следующий шаг — создать каталог регистрации в пути поиска, а затем добавить файл login.html.

Каталог шаблонов

URL-адреса (и неявные представления), которые мы только что добавили, ожидают найти связанные с ними шаблоны в каталоге / регистрации / где-то в пути поиска шаблонов.

Для этого сайта мы разместим наши HTML-страницы в каталоге templates / registration /. Этот каталог должен находиться в корневом каталоге проекта, то есть в том же каталоге, что и в каталоге и папках locallibrary). Создайте эти папки сейчас.

Примечание: ваша структура папок теперь должна выглядеть как показано внизу: locallibrary (django project folder) |_catalog |_locallibrary |_templates (new) |_registration

Чтобы сделать эти директории видимыми для загрузчика шаблонов (т. е. помещать этот каталог в путь поиска шаблона) откройте настройки проекта (/locallibrary/locallibrary/settings.py), и обновите в секции TEMPLATES строку ‘DIRS’ как показано.

= [  ... 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, ... 

Шаблон аутентификации

Предупреждение: Важно: Шаблоны аутентификации, представленные в этой статье, являются очень простой / слегка изменённой версией шаблонов логина демонстрации Django. Возможно, вам придётся настроить их для собственного использования!

Создайте новый HTML файл, названный /locallibrary/templates/registration/login.html. дайте ему следующее содержание:

 extends "base_generic.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> p>a href=" url 'password_reset' %>">Lost password?a>p>  endblock %> 

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

Перейдите на страницу входа ( http://127.0.0.1:8000/accounts/login/ ) когда вы сохраните свой шаблон, и вы должны увидеть что-то наподобие этого:

Library login page v1

Если ваша попытка войти в систему будет успешной, вы будете перенаправлены на другую страницу (по умолчанию это будет http://127.0.0.1:8000/accounts/profile/ ). Проблема здесь в том, что по умолчанию Django ожидает, что после входа в систему вы захотите перейти на страницу профиля, что может быть или не быть. Поскольку вы ещё не определили эту страницу, вы получите ещё одну ошибку!

Откройте настройки проекта (/locallibrary/locallibrary/settings.py) и добавьте текст ниже. Теперь, когда вы входите в систему, вы по умолчанию должны перенаправляться на домашнюю страницу сайта.

# Redirect to home URL after login (Default redirects to /accounts/profile/) LOGIN_REDIRECT_URL = '/' 

Шаблон выхода

Если вы перейдёте по URL-адресу выхода ( http://127.0.0.1:8000/accounts/logout/ ), то увидите странное поведение — ваш пользователь наверняка выйдет из системы, но вы попадёте на страницу выхода администратора. Это не то, что вам нужно, хотя бы потому, что ссылка для входа на этой странице приведёт вас к экрану входа в систему администратора. (и это доступно только для пользователей, у которых есть разрешение is_staff ).

Создайте и откройте /locallibrary/templates/registration/logged_out.html. Скопируйте текст ниже:

 extends "base_generic.html" %>  block content %> p>Logged out!p> a href=" url 'login'%>">Click here to login again.a>  endblock %> 

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

Шаблон сброса пароля

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

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

Форма сброса пароля

Это форма, используемая для получения адреса электронной почты пользователя (для отправки пароля для сброса пароля). Создайте /locallibrary/templates/registration/password_reset_form.html и дайте ему следующее содержание:

 extends "base_generic.html" %>  block content %> form action="" method="post"> csrf_token %>  if form.email.errors %>  <form.email.errors >>  endif %> p> <form.email >>p> input type="submit" class="btn btn-default btn-lg" value="Reset password" /> form>  endblock %> 
Сброс пароля

Эта форма отображается после того, как ваш адрес электронной почты будет собран. Создайте /locallibrary/templates/registration/password_reset_done.html, и дайте ему следующее содержание:

 extends "base_generic.html" %>  block content %> p> We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder. p>  endblock %> 
Сброс пароля по email

Этот шаблон предоставляет текст электронной почты HTML, содержащий ссылку на сброс, которую мы отправим пользователям. Создайте /locallibrary/templates/registration/password_reset_email.html и дайте ему следующее содержание:

 email >>. Follow the link below:  protocol>>:// domain >> url 'password_reset_confirm' uidb64=uid token=token %> 
Подтверждение на сброс пароля

На этой странице вы вводите новый пароль после нажатия ссылки в электронном письме с возвратом пароля. Создайте /locallibrary/templates/registration/password_reset_confirm.html и дайте ему следующее содержание:

 extends "base_generic.html" %>  block content %>  if validlink %> p>Please enter (and confirm) your new password.p> form action="" method="post">  csrf_token %> table> tr> td>  <form.new_password1.errors >> label for="id_new_password1">New password:label> td> td> <form.new_password1 >>td> tr> tr> td>  <form.new_password2.errors >> label for="id_new_password2">Confirm password:label> td> td> <form.new_password2 >>td> tr> tr> td>td> td>input type="submit" value="Change my password" />td> tr> table> form>  else %> h1>Password reset failedh1> p> The password reset link was invalid, possibly because it has already been used. Please request a new password reset. p>  endif %>  endblock %> 
Сброс пароля завершён

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

 extends "base_generic.html" %>  block content %> h1>The password has been changed!h1> p>a href=" url 'login' %>">log in again?a>p>  endblock %> 

Тестирование новых страниц аутентификации

Теперь, когда вы добавили конфигурацию URL и создали все эти шаблоны, теперь страницы аутентификации должны работать! Вы можете протестировать новые страницы аутентификации, попытавшись войти в систему, а затем выйдите из учётной записи суперпользователя, используя эти URL-адреса:

  • http://127.0.0.1:8000/accounts/login/
  • http://127.0.0.1:8000/accounts/logout/

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

Примечание: Система сброса пароля требует, чтобы ваш сайт поддерживал электронную почту, что выходит за рамки этой статьи, поэтому эта часть ещё не будет работать. Чтобы разрешить тестирование, поместите следующую строку в конец файла settings.py. Это регистрирует любые письма, отправленные на консоль (чтобы вы могли скопировать ссылку на сброс пароля с консоли).

= 'django.core.mail.backends.console.EmailBackend' 

Для получения дополнительной информации см. Отправка email (Django docs).

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

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

Тестирование в шаблонах

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

Обычно вы сначала проверяете переменную шаблона >, чтобы определить, имеет ли пользователь право видеть конкретный контент. Чтобы продемонстрировать это, мы обновим нашу боковую панель, чтобы отобразить ссылку «Вход», если пользователь вышел из системы, и ссылку «Выход», если он вошёл в систему.

Откройте базовый шаблон (/locallibrary/catalog/templates/base_generic.html) и скопируйте следующий текст в sidebar блок непосредственно перед тегом шаблона endblock.

ul class="sidebar-nav"> ... % if user.is_authenticated %> li>User:  user.get_username >>/li> li>a href="?next=>">Logout/a>/li> % else %> li>a href="?next=>">Login/a>/li> % endif %> /ul> 

Как вы можете видеть, мы используем теги шаблона if-else-endif для условного отображения текста на основе того, является ли > истинным. Если пользователь аутентифицирован, мы знаем, что у нас есть действительный пользователь, поэтому мы вызываем >, чтобы отобразить их имя.

Мы создаём URL-адрес для входа и выхода из системы, используя тег шаблона URL-адреса и имена соответствующих конфигураций URLs. Также обратите внимание на то, как мы добавили ?next=> в конец URLs. Это означает, что следующий URL-адрес содержит адрес (URL) текущей страницы, в конце связанного URL-адреса. После того, как пользователь успешно выполнил вход в систему, представления будут использовать значение » next » чтобы перенаправить пользователя обратно на страницу, где они сначала нажали ссылку входа / выхода из системы.

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

Тестирование в представлениях

Если вы используете функциональные представления, самым простым способом ограничить доступ к вашим функциям является применение login_required декоратор к вашей функции просмотра, как показано ниже. Если пользователь вошёл в систему, ваш код просмотра будет выполняться как обычно. Если пользователь не вошёл в систему, это перенаправит URL-адрес входа, определённый в настройках проекта. ( settings.LOGIN_URL ), передав текущий абсолютный путь в качестве next параметра URL. Если пользователю удастся войти в систему, они будут возвращены на эту страницу, но на этот раз аутентифицированы.

from django.contrib.auth.decorators import login_required @login_required def my_view(request): ... 

Примечание: Вы можете сделать то же самое вручную, путём тестирования request.user.is_authenticated , но декоратор намного удобнее!

Аналогичным образом, самый простой способ ограничить доступ к зарегистрированным пользователям в ваших представлениях на основе классов — это производные от LoginRequiredMixin . Вы должны объявить этот mixin сначала в списке суперкласса, перед классом основного представления.

from django.contrib.auth.mixins import LoginRequiredMixin class MyView(LoginRequiredMixin, View): ... 

Это имеет такое же поведение при переадресации, что и login_required декоратор. Вы также можете указать альтернативное местоположение для перенаправления пользователя, если он не аутентифицирован ( login_url ), и имя параметра URL вместо » next » , чтобы вставить текущий абсолютный путь ( redirect_field_name ).

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

Для получения дополнительной информации ознакомьтесь с Django docs here.

Пример — перечисление книг текущего пользователя

Теперь, когда мы знаем, как ограничить страницу определённому пользователю, создайте представление о книгах, которые заимствовал текущий пользователь.

К сожалению, у нас пока нет возможности пользователям использовать книги! Поэтому, прежде чем мы сможем создать список книг, мы сначала расширим BookInstance модель для поддержки концепции заимствования и использования приложения Django Admin для заимствования ряда книг нашему тестовому пользователю.

Модели

Прежде всего, мы должны предоставить пользователям возможность кредита на BookInstance (у нас уже есть status и due_back дата, но у нас пока нет связи между этой моделью и пользователем. Мы создадим его с помощью поля ForeignKey (один ко многим). Нам также нужен простой механизм для проверки того, просрочена ли заёмная книга.

Откройте catalog/models.py, и импортируйте модель User из django.contrib.auth.models (добавьте это чуть ниже предыдущей строки импорта в верхней части файла, так User доступен для последующего кода, что позволяет использовать его):

from django.contrib.auth.models import User 

Затем добавьте поле borrower в модель BookInstance :

= models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) 

Пока мы здесь, давайте добавим свойство, которое мы можем вызвать из наших шаблонов, чтобы указать, просрочен ли конкретный экземпляр книги. Хотя мы могли бы рассчитать это в самом шаблоне, использование свойства, как показано ниже, будет намного более эффективным. Добавьте это где-нибудь в верхней части файла:

from datetime import date

Теперь добавьте следующее определение свойства внутри класса BookInstance:

@property def is_overdue(self): if self.due_back and date.today() > self.due_back: return True return False 

Примечание: Сначала мы проверим, является ли due_back пустым, прежде чем проводить сравнение. Пустое поле due_back заставило Django выкидывать ошибку, а не показывать страницу: пустые значения не сопоставимы. Это не то, что мы хотели бы, чтобы наши пользователи испытывали!

Теперь, когда мы обновили наши модели, нам нужно будет внести новые изменения в проект, а затем применить эти миграции:

Admin

Теперь откройте каталог catalog/admin.py, и добавьте поле borrower в класс BookInstanceAdmin , как в list_display , так и в полях fieldsets , как показано ниже. Это сделает поле видимым в разделе Admin, так что мы можем при необходимости назначить User в BookInstance.

python
@admin.register(BookInstance) class BookInstanceAdmin(admin.ModelAdmin): list_display = ('book', 'status', 'borrower', 'due_back', 'id') list_filter = ('status', 'due_back') fieldsets = ( (None,  'fields': ('book','imprint', 'id') >), ('Availability',  'fields': ('status', 'due_back','borrower') >), ) 

Займите несколько книг

Теперь, когда возможно кредитовать книги конкретному пользователю, зайдите и заработайте на нескольких записей в BookInstance . Установите borrowed поле вашему тестовому пользователю, сделайте status «В займе» и установите сроки оплаты как в будущем, так и в прошлом.

Примечание: Мы не будем описывать процесс, так как вы уже знаете, как использовать Admin сайт!

Займ в представлении

Теперь мы добавим представление для получения списка всех книг, которые были предоставлены текущему пользователю. Мы будем использовать один и тот же общий класс, с которым мы знакомы, но на этот раз мы также будем импортировать и выводить из LoginRequiredMixin , так что только вошедший пользователь сможет вызвать это представление. Мы также решили объявить template_name , вместо того, чтобы использовать значение по умолчанию, потому что у нас может быть несколько разных списков записей BookInstance, с разными представлениями и шаблонами.

Добавьте следующее в catalog/views.py:

from django.contrib.auth.mixins import LoginRequiredMixin class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView): """ Generic class-based view listing books on loan to current user. """ model = BookInstance template_name ='catalog/bookinstance_list_borrowed_user.html' paginate_by = 10 def get_queryset(self): return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back') 

Чтобы ограничить наш запрос только объектами BookInstance для текущего пользователя, мы повторно реализуем get_queryset() , как показано выше. Обратите внимание, что "o" это сохранённый код для "on loan" и мы сортируем по дате due_back , чтобы сначала отображались самые старые элементы.

URL-адрес для заёмных книг

Теперь откройте /catalog/urls.py и добавьте url() , указывая на приведённое выше представление (вы можете просто скопировать текст ниже в конец файла).

+= [ url(r'^mybooks/$', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'), ] 

Шаблон для заёмных книг

Теперь все, что нам нужно сделать для этой страницы, - это добавить шаблон. Сначала создайте файл шаблона /catalog/templates/catalog/bookinstance_list_borrowed_user.html и дайте ему следующее содержание:

% extends "base_generic.html" %> % block content %> h1>Borrowed books/h1> % if bookinstance_list %> ul> % for bookinst in bookinstance_list %> li class="text-danger"> a href="">bookinst.book.title>>/a> ( bookinst.due_back >>) /li> % endfor %> /ul> % else %> p>There are no books borrowed./p> % endif %> % endblock %> 

Этот шаблон очень похож на тот, который мы создали ранее для объектов Book и Author . Единственное, что «новое» здесь, это то, что мы проверяем метод, который мы добавили в модель (bookinst.is_overdue ) с целью использовать его для изменения цвета просроченных предметов.

Когда сервер разработки запущен, вы должны теперь иметь возможность просматривать список для зарегистрированного пользователя в своём браузере по адресу http://127.0.0.1:8000/catalog/mybooks/ . Попробуйте это, когда ваш пользователь войдёт в систему и выйдет из системы (во втором случае вы должны быть перенаправлены на страницу входа в систему).

Добавить список на боковую панель

Последний шаг - добавить ссылку на эту новую страницу в sidebar. Мы поместим это в тот же раздел, где мы покажем другую информацию для зарегистрированного пользователя.

Откройте базовый шаблон (/locallibrary/catalog/templates/base_generic.html) и добавьте выделенную строку из sidebar, как показано на рисунке.

ul class="sidebar-nav"> % if user.is_authenticated %> li>User:  user.get_username >>/li> li>a href="">My Borrowed/a>/li> li>a href="?next=>">Logout/a>/li> % else %> li>a href="?next=>">Login/a>/li> % endif %> /ul> 

На что это похоже?

Когда любой пользователь войдёт в систему, он будет видеть ссылку «Мной позаимствовано (My Borrowed)» в боковой колонке, и список книг, показанных ниже (первая книга не имеет установленной даты, что является ошибкой, которую мы надеемся исправить в более позднем уроке!).

Library - borrowed books by user

Права доступа

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

Модели

Определение разрешений выполняется в разделе моделей " class Meta " , используется permissions поле. Вы можете указать столько разрешений, сколько необходимо в кортеже, причём каждое разрешение определяется во вложенном кортеже, содержащем имя разрешения и отображаемое значение разрешения. Например, мы можем определить разрешение, позволяющее пользователю отметить, что книга была возвращена, как показано здесь:

class BookInstance(models.Model): ... class Meta: ... permissions = (("can_mark_returned", "Set book as returned"),) 

Затем мы могли бы назначить разрешение группе «Библиотекарь» (Librarian) на сайте администратора.

Откройте catalog/models.py, и добавьте разрешение, как показано выше. Вам нужно будет повторно выполнить миграцию (вызвав python3 manage.py makemigrations и python3 manage.py migrate ) для надлежащего обновления базы данных.

Шаблоны

Разрешения текущего пользователя хранятся в переменной шаблона, называемой > . Вы можете проверить, имеет ли текущий пользователь определённое разрешение, используя конкретное имя переменной в соответствующем приложении «Django» - например, > будет True если у пользователя есть это разрешение, а False - в противном случае. Обычно мы проверяем разрешение с использованием шаблона , как показано в:

% if perms.catalog.can_mark_returned %> !-- We can mark a BookInstance as returned. --> !-- Perhaps add code to link to a "book return" view here. --> % endif %> 

Представления

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

Функция в представлении с декоратором:

from django.contrib.auth.decorators import permission_required @permission_required('catalog.can_mark_returned') @permission_required('catalog.can_edit') def my_view(request): ... 

Требуется разрешение mixin для представлений на основе классов.

from django.contrib.auth.mixins import PermissionRequiredMixin class MyView(PermissionRequiredMixin, View): permission_required = 'catalog.can_mark_returned' # Or multiple permissions permission_required = ('catalog.can_mark_returned', 'catalog.can_edit') # Note that 'catalog.can_edit' is just an example # the catalog application doesn't have such permission! 

Пример

Мы не будем обновлять LocalLibrary здесь; возможно, в следующем уроке!

Испытайте себя

Ранее в этой статье мы показали вам, как создать страницу для текущего пользователя, в которой перечислены книги, которые они заимствовали. Теперь задача состоит в том, чтобы создать аналогичную страницу, которая видна только для библиотекарей, которая отображает все книги, которые были заимствованы, и которая показывает имя каждого заёмщика.

Вы должны следовать той же схеме, что и для другого представления. Главное отличие состоит в том, что вам нужно ограничить представление только библиотекарями. Вы можете сделать это на основе того, является ли пользователь сотрудником (декоратор функции: staff_member_required , переменная шаблона: user.is_staff ) но мы рекомендуем вам вместо этого использовать can_mark_returned разрешения и PermissionRequiredMixin , как описано в предыдущем разделе.

Предупреждение: Важно: Не забудьте использовать вашего суперпользователя для тестирования на основе разрешений (проверки разрешений всегда возвращают true для суперпользователей, даже если разрешение ещё не определено!). Вместо этого создайте пользователя-библиотекаря и добавьте необходимые возможности.

Когда вы закончите, ваша страница должна выглядеть примерно, как на скриншоте ниже.

All borrowed books, restricted to librarian

Подводим итоги

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

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

Смотрите также

  • User authentication in Django (Django docs)
  • Using the (default) Django authentication system (Django docs)
  • Introduction to class-based views > Decorating class-based views (Django docs)
  • Назад
  • Обзор: Django
  • Далее

Found a content problem with this page?

  • Edit the page on GitHub.
  • Report the content issue.
  • View the source on GitHub.

This page was last modified on 3 авг. 2023 г. by MDN contributors.

Your blueprint for a better internet.

Модель пользователя Django – создание и настройка

Django поставляется с отличной встроенной моделью пользователя и поддержкой аутентификации. Это основная причина, по которой большинство разработчиков предпочитают Django Flask, FastAPI, AIOHttp и многим другим фреймворкам.

Но иногда нам не нравится модель User или мы хотим настраивать ее в соответствии с требованиями проекта. Предположим, нам больше не нужно поле имени пользователя. Или мы хотим использовать электронную почту пользователя вместо имени пользователя по умолчанию. Для этого нам нужно настроить нашу модель пользователя Django по умолчанию.

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

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

Если вы новичок в Django, посетите наш учебник по Django.

Начало

  • Установите последнюю версию Django (2.2+);
  • Создайте проект Django;
  • Сделайте базовую настройку;
  • Создайте виртуальную среду.

Создание проекта пользователя в Django

Наш первый шаг — создать приложение в проекте с помощью следующей команды.

python manage.py startapp MyUserModel

Приложение будет создано в каталоге проекта. Теперь зарегистрируйте приложение в файле settings.py.

INSTALLED_APP = [ . . MyUserModel ]

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

Теперь мы создадим пользовательскую моделья в файле models.py. Давайте посмотрим следующий код.

from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin from django.utils import timezone from django.utils.translation import gettext_lazy as _ from .managers import CustomUserManager # Create your models here. class CustomUser(AbstractBaseUser, PermissionsMixin): username = None email = models.EmailField(_('email_address'), unique=True, max_length = 200) date_joined = models.DateTimeField(default=timezone.now) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] objects = CustomUserManager() def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def is_staff(self): "Is the user a member of staff?" return self.staff @property def is_admin(self): "Is the user a admin member?" return self.admin def __str__(self): return self.email

Давайте разберемся с приведенной выше моделью; мы создали класс CustomUser, который наследует AbstractbaseClass. Затем мы добавили поле для электронной почты, is_staff, is_active и date_joined.

  • Имя пользователя установлено равным none, потому что мы хотим аутентифицировать пользователя по его уникальному идентификатору электронной почты, а не по имени.
  • is_staff возвращает true, если пользователь разрешает вход в панель администратора.
  • is_active возвращает true, если пользователь в данный момент активен. Если пользователь не активен, он не позволит войти в систему.
  • USERNAME_FIELDS определяет уникальную идентификацию для модели пользователя — по электронной почте.
  • REQUIRED_FIELDS запрашивает поля, когда мы создаем суперпользователя с помощью команды createsuperuser. Он должен включать любое поле, для которого пустым является False.
  • Объект класса менеджера указывает, что все объекты для класса поступают из CustomeUserManager. has_permission возвращает true, если у пользователя есть каждое из указанных разрешений.

Создание Model Manager

Django предоставляет встроенные методы для менеджера пользователей. Но если мы создаем пользовательскую модель, нам нужно переопределить методы по умолчанию. Создайте новый файл manager.py (можно изменить) и создайте User Model Manager. Ниже методы предоставляются BaseUserManager.

from django.contrib.auth.base_user import BaseUserManager from django.utils.translation import ugettext_lazy as _ """ Custom user model manager where email is the unique identifiers for authentication instead of usernames. """ class CustomUserManager(BaseUserManager): """ Custom user model manager where email is the unique identifiers for authentication instead of usernames. """ def create_user(self, email, password, **extra_fields): """ Create and save a User with the given email and password. """ if not email: raise ValueError(_('The Email must be set')) email = self.normalize_email(email) user = self.model(email=email, **extra_fields) user.set_password(password) user.save() return user def create_superuser(self, email, password, **extra_fields): """ Create and save a SuperUser with the given email and password. """ extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_active', 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 get_full_name(self): ''' Returns the first_name plus the last_name, with a space in between. ''' full_name = '%s %s' %(self.first_name, self.last_name) return full_name.strip() def get_short_name(self): ''' Returns the short name for the user. ''' return self.first_name

Мы создали CustomManagerClass, который наследует BaseUserManager. Он предоставляет следующие вспомогательные методы.

  • Метод create_user() создает, сохраняет и возвращает пользователя. Он автоматически преобразует электронную почту в нижний регистр, а возвращаемый объект User будет иметь значение is_active, равное true.
  • Метод create_superuser() устанавливает для is_staff и is_active значение True.
  • get_full_name() возвращает полное имя пользователя.
  • get_short_name возвращает first_name пользователя.

Регистрация пользователя в settings.py

Созданную пользовательскую модель необходимо зарегистрировать в файле settings.py, иначе Django будет считать ее User моделью. Это будет ошибочно. Откройте файл settings.py и зарегистрируйте созданную пользовательскую модель.

AUTH_USER_MODEL = appName.ClassName

В нашем случае это будет –

AUTH _USER_MODEL = MyUserModel.CustomUser

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

python manage.py makemigrations python manage.py migrate

Мы получим файл миграции, как показано ниже.

# Generated by Django 3.2.6 on 2021-08-09 19:55 from django.db import migrations, models import django.utils.timezone class Migration(migrations.Migration): initial = True dependencies = [ ('auth', '0012_alter_user_first_name_max_length'), ] operations = [ migrations.CreateModel( name='CustomerUser', 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')), ('email', models.EmailField(max_length=254, unique=True, verbose_name='email_address')), ('is_staff', models.BooleanField(default=False)), ('is_active', models.BooleanField(default=True)), ('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=< 'abstract': False, >, ), ]

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

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

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

python manage.py createsuperuser

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

Email address: [email protected] Password: Password(again): Superuser created successfully.

Создание формы для хранения информации о пользователе

Мы создадим форму, используя формы подкласса UserCreationForm по умолчанию, чтобы они могли использовать нашу пользовательскую модель.

Давайте создадим файл forms.py в «MyUserModel».

from django.contrib.auth.forms import UserCreationForm, UserChangeForm from django.db.models import fields from django import forms from .models import CustomerUser from django.contrib.auth import get_user_model User = get_user_model() class CustomUserCreationForm(UserCreationForm): password1 = forms.CharField(widget=forms.PasswordInput) password2 = forms.CharField(label='Confirm Password', widget=forms.PasswordInput) class Meta: model = CustomerUser fields =('email', ) def clean_email(self): email = self.cleaned_data.get('email') qs = User.objects.filter(email=email) if qs.exists(): raise forms.ValidationError("Email is taken") return email def clean(self): ''' Verify both passwords match. ''' cleaned_data = super().clean() password1 = cleaned_data.get("password1") password2 = cleaned_data.get("password2") if password1 is not None and password1 != password2: self.add_error("password2", "Your passwords must match") return cleaned_data def save(self, commit=True): # Save the provided password in hashed format user = super().save(commit=False) user.set_password(self.cleaned_data["password1"]) if commit: user.save() return user class CustomUserChangeForm(UserChangeForm): class Meta: model = CustomerUser fields =('email', ) def clean_password(self): # Regardless of what the user provides, return the initial value. # This is done here, rather than on the field, because the # field does not have access to the initial value return self.initial["password1"]

Класс CustomUserCreationForm наследует UsecreationForm, который состоит из трех полей: имя пользователя, пароль1 и пароль2. Пароль1 совпадает с паролем2; если оба пароля совпадают, то validate_password() проверяет пароль и устанавливает пароль пользователя с помощью set_password(). Пароль будет сохранен в хешированном формате.

Теперь настроим панель администратора.

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

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

from django.contrib import admin from django.contrib.auth import authenticate from django.contrib.auth.admin import UserAdmin # Register your models here. class CustomUserAdmin(UserAdmin): add_form = CustomUserCreationForm form = CustomUserChangeForm model = CustomerUser list_display =('email', 'is_staff', 'is_active',) list_filter =('email', 'is_staff', 'is_active',) fieldsets =( (None, <'fields':('email', 'password')>), ('Permissions', <'fields':('is_staff', 'is_active')>), ) add_fieldsets =( (None, < 'classes':('wide',), 'fields':('email', 'password1', 'password2', 'is_staff', 'is_active')>), ) search_fields =('email',) ordering =('email',) filter_horizontal =() admin.site.register(CustomerUser, CustomUserAdmin)

Теперь мы готовы создать нового пользователя. Выполните следующую команду и войдите в панель администратора с учетными данными суперпользователя.

Пользовательская модель Django

После входа в админ-панель мы видим кнопку ADD CUSTOM USER, где создаем новых пользователей.

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

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

Панель администратора

Вывод

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

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

Добавить комментарий

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