views.py
...
@login_required
def topics(request):
...
@login_required
def topic(request, topic_id):
...
@login_required
def new_topic(request):
...
@login_required
def new_entry(request, topic_id):
...
@login_required
def edit_entry(request, entry_id):
...
430 Глава 19 • Учетные записи пользователей
Попробуйте обратиться к любой из этих страниц без выполнения входа: вы будете пере-
направлены обратно на страницу входа. Кроме того, вы не сможете щелкать на ссылках
на такие страницы, как
new_topic
. Но если ввести URL http://localhost:8000/new_topic/,
вы будете перенаправлены на страницу входа. Ограничьте доступ ко всем URL-адресам,
связанным с личными данными пользователей.
Связывание данных с конкретными пользователями
Теперь данные, отправленные пользователем, необходимо связать с тем пользо-
вателем, который их отправил. Связь достаточно установить только с данными,
находящимися на высшем уровне иерархии, а низкоуровневые данные последуют
за ними автоматически. Например, в приложении Learning Log на высшем уровне
находятся темы, а каждая запись связывается с некоторой темой. Если каждая тема
принадлежит конкретному пользователю, мы сможем отследить владельца каждой
записи в базе данных.
Изменим модель
Topic
и добавим отношение внешнего ключа с пользователем.
После этого необходимо провести миграцию базы данных. Наконец, необходимо
изменить некоторые представления, чтобы в них отображались только данные,
связанные с текущим пользователем.
Изменение модели Topic
В файле
models .py
изменяются всего две строки:
models.py
from django.db import models
from django.contrib.auth.models import User
class Topic(models.Model):
"""Тема, которую изучает пользователь"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User)
def __str__(self):
"""Возвращает строковое представление модели."""
return self.text
class Entry(models.Model):
...
Сначала модель
User
импортируется из
django.contrib.auth
. Затем в
Topic
до-
бавляется поле
owner
, используемое в отношении внешнего ключа с моделью
User
.
Идентификация существующих пользователей
При проведении миграции Django модифицирует базу данных, чтобы в ней хра-
нилась связь между каждой темой и пользователем. Для выполнения миграции
Django необходимо знать, с каким пользователем должна быть связана каждая
существующая тема. Проще всего связать все существующие темы с одним поль-
Редактирование данных 431
зователем, например суперпользователем. Но для этого сначала необходимо узнать
идентификатор этого пользователя.
Просмотрим идентификаторы всех пользователей, созданных до настоящего мо-
мента. Запустите сеанс оболочки Django и введите следующие команды:
(venv)learning_log$ python manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.all()
[, , ]
>>> for user in User.objects.all():
... print(user.username, user.id)
...
ll_admin 1
eric 2
willie 3
>>>
В точке в сеанс оболочки импортируется модель
User
. После этого просматрива-
ются все пользователи, созданные до настоящего момента . В выходных данных
перечислены три пользователя: ll_admin, eric и willie.
В точке перебирается список пользователей, и для каждого пользователя вы-
водится его имя и идентификатор. Когда Django спросит, с каким пользователем
связать существующие темы, мы используем один из этих идентификаторов.
Миграция базы данных
Зная значение идентификатора, можно провести миграцию базы данных.
(venv)learning_log$ python manage.py makemigrations learning_logs
You are trying to add a non-nullable field 'owner' to topic without a default;
we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
Select an option: 1
Please enter the default value now, as valid Python
The datetime and django.utils.timezone modules are available, so you can do
e.g. timezone.now()
>>> 1
Migrations for 'learning_logs':
0003_topic_owner.py:
- Add field owner to topic
Сначала выдается команда
makemigrations
. В ее выходных данных Django со-
общает, что мы пытаемся добавить обязательное поле (значения которого отличны
от null) в существующую модель (
topic
) без указания значения по умолчанию.
Django предоставляет два варианта : мы можем либо указать значение по умол-
чанию прямо сейчас, либо завершить выполнение программы и добавить значение
по умолчанию в
models .py
. В точке выбирается первый вариант. Тогда Django
запрашивает значение по умолчанию .
Чтобы связать все существующие темы с исходным административным пользо-
вателем
ll_admin
, я ввел в точке
идентификатор пользователя 1. Вы можете
432 Глава 19 • Учетные записи пользователей
использовать идентификатор любого из созданных пользователей; он не обязан
быть суперпользователем. Django проводит миграцию базы данных, используя это
значение, и создает файл миграции
0003_topic_owner .py
, добавляющий поле
owner
в модель
Topic
.
Теперь можно провести миграцию. Введите следующую команду в активной вир-
туальной среде:
(venv)learning_log$ python manage.py migrate
Operations to perform:
Synchronize unmigrated apps: messages, staticfiles
Apply all migrations: learning_logs, contenttypes, sessions, admin, auth
...
Running migrations:
Rendering model states... DONE
Applying learning_logs.0003_topic_owner...
OK
(venv)learning_log$
Django применяет новую миграцию с результатом
OK
. Чтобы убедиться в том, что
миграция сработала так, как и ожидалось, можно воспользоваться интерактивной
оболочкой:
>>> from learning_logs.models import Topic
>>> for topic in Topic.objects.all():
... print(topic, topic.owner)
...
Chess ll_admin
Rock Climbing ll_admin
>>>
После импортирования
Topic
из
learning_logs.models
мы перебираем все су-
ществующие темы, выводим каждую тему и имя пользователя, которому она при-
надлежит . Как видите, сейчас каждая тема принадлежит пользователю
ll_admin
.
Достарыңызбен бөлісу: |