Написание вашего первого приложения Django, часть 2 ¶
Этот учебник начинается с того места, где остановился Урок 1 . Мы настроим базу данных, создадим вашу первую модель и быстро познакомимся с автоматически сгенерированным сайтом администратора Django.
Где получить помощь:
Если у вас возникли проблемы с прохождением этого руководства, перейдите в раздел « Получение справки » в FAQ.
Настройка базы данных ¶
А теперь открой mysite/settings.py
. Это обычный модуль Python с переменными уровня модуля, представляющими настройки Django.
По умолчанию в конфигурации используется SQLite. Если вы новичок в базах данных или просто хотите попробовать Django, это самый простой выбор. SQLite включен в Python, поэтому вам не нужно ничего устанавливать для поддержки вашей базы данных. Однако при запуске вашего первого реального проекта вы можете захотеть использовать более масштабируемую базу данных, такую как PostgreSQL, чтобы избежать головной боли при переключении базы данных в будущем.
Если вы хотите использовать другую базу данных, установите соответствующие привязки базы данных и измените следующие ключи в
элементе, чтобы они соответствовали настройкам подключения к базе данных:DATABASES
'default'
ENGINE
- Либо'django.db.backends.sqlite3'
,'django.db.backends.postgresql'
,'django.db.backends.mysql'
или'django.db.backends.oracle'
. Также доступны другие бэкенды .NAME
- Название вашей базы данных. Если вы используете SQLite, база данных будет файлом на вашем компьютере; в этом случаеNAME
должен быть полный абсолютный путь, включая имя файла, этого файла. Значение по умолчанию, сохранит файл в каталоге вашего проекта.BASE_DIR / 'db.sqlite3'
Если вы не используете SQLite в качестве базы данных, дополнительные параметры , такие как
USER
, PASSWORD
и HOST
должны быть добавлены. Дополнительные сведения см. В справочной документации по DATABASES
.
Для баз данных, отличных от SQLite
Если вы используете базу данных помимо SQLite, убедитесь, что к этому моменту вы уже создали базу данных. Сделайте это с помощью « » в интерактивной подсказке вашей базы данных.CREATE DATABASE database_name;
Также убедитесь, что указанный пользователь базы данных mysite/settings.py
имеет права «создать базу данных». Это позволяет автоматически создавать
тестовую базу данных, которая понадобится в следующем учебнике.
Если вы используете SQLite, вам не нужно ничего создавать заранее - файл базы данных будет создан автоматически, когда это необходимо.
Пока вы редактируете mysite/settings.py
, установите TIME_ZONE
свой часовой пояс.
Также обратите внимание на INSTALLED_APPS
настройку в верхней части файла. Он содержит имена всех приложений Django, которые активированы в этом экземпляре Django. Приложения можно использовать в нескольких проектах, и вы можете упаковывать и распространять их для использования другими в их проектах.
По умолчанию INSTALLED_APPS
содержит следующие приложения, все из которых поставляются с Django:
django.contrib.admin
- Админка сайта. Скоро ты им воспользуешься.django.contrib.auth
- Система аутентификации.django.contrib.contenttypes
- Фреймворк для типов контента.django.contrib.sessions
- Фреймворк сеанса.django.contrib.messages
- Фреймворк для обмена сообщениями.django.contrib.staticfiles
- Фреймворк для управления статическими файлами.
Эти приложения включены по умолчанию для удобства в общем случае.
Однако некоторые из этих приложений используют по крайней мере одну таблицу базы данных, поэтому нам нужно создать таблицы в базе данных, прежде чем мы сможем их использовать. Для этого выполните следующую команду:
$ python manage.py migrate
... \> py manage.py migrate
Команда migrate
просматривает INSTALLED_APPS
настройку и создает все необходимые таблицы базы данных в соответствии с настройками базы данных в вашем mysite/settings.py
файле и миграциями базы данных, поставляемыми с приложением (мы рассмотрим их позже). Вы увидите сообщение для каждой применяемой миграции. Если вам интересно, запустите клиент командной строки для своей базы данных и введите \dt
(PostgreSQL), (MariaDB, MySQL),
(SQLite) или (Oracle), чтобы отобразить таблицы, созданные Django.SHOW TABLES;
.schema
SELECT TABLE_NAME FROM USER_TABLES;
Для минималистов
Как мы уже говорили выше, приложения по умолчанию включены для общего случая, но они нужны не всем. Если вам не нужны какие-либо из них или все, не стесняйтесь закомментировать или удалить соответствующие строки
INSTALLED_APPS
перед запуском migrate
. Команда
migrate
будет запускать миграции только для приложений в
INSTALLED_APPS
.
Создание моделей ¶
Теперь мы определим ваши модели - по сути, макет вашей базы данных с дополнительными метаданными.
Философия
Модель - это единственный окончательный источник правды о ваших данных. Он содержит основные поля и поведение данных, которые вы храните. Django следует принципу DRY . Цель состоит в том, чтобы определить вашу модель данных в одном месте и автоматически извлекать из нее данные.
Это включает в себя миграции - в отличие, например, от Ruby On Rails, миграции полностью основаны на вашем файле моделей и, по сути, представляют собой историю, которую Django может прокручивать, чтобы обновить схему вашей базы данных в соответствии с вашими текущими моделями.
В нашем приложении для опроса мы создадим две модели: Question
и Choice
. У A
Question
есть вопрос и дата публикации. A Choice
имеет два поля: текст выбора и подсчет голосов. Каждый Choice
связан с файлом Question
.
Эти концепции представлены классами Python. Отредактируйте
polls/models.py
файл так, чтобы он выглядел так:
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
Здесь каждая модель представлена классом, который является подклассом
django.db.models.Model
. Каждая модель имеет ряд переменных класса, каждая из которых представляет поле базы данных в модели.
Каждое поле представлено экземпляром Field
класса - например, CharField
для символьных полей и DateTimeField
для даты и
времени. Это сообщает Django, какой тип данных содержит каждое поле.
Имя каждого Field
экземпляра (например,
question_text
или pub_date
) - это имя поля в машинно-понятном формате. Вы будете использовать это значение в своем коде Python, а ваша база данных будет использовать его в качестве имени столбца.
Вы можете использовать необязательный первый позиционный аргумент
Field
для обозначения удобочитаемого имени. Он используется в нескольких интроспективных частях Django и служит документацией. Если это поле не указано, Django будет использовать машиночитаемое имя. В этом примере мы определили только удобочитаемое имя для Question.pub_date
. Для всех других полей в этой модели достаточно машиночитаемого имени поля в качестве его удобочитаемого имени.
У некоторых Field
классов есть обязательные аргументы.
CharField
, например, требует, чтобы вы присвоили ему
max_length
. Это используется не только в схеме базы данных, но и при проверке, как мы скоро увидим.
А Field
также может иметь различные необязательные аргументы; в данном случае мы установили default
значение
votes
0.
Наконец, обратите внимание, что связь определяется с помощью
ForeignKey
. Это говорит Django, что каждый из Choice
них связан с одним Question
. Django поддерживает все стандартные отношения между базами данных: «многие к одному», «многие ко многим» и «один к одному».
Активация моделей ¶
Этот небольшой фрагмент кода модели дает Django много информации. С его помощью Django может:
- Создайте схему ( операторы) базы данных для этого приложения.
CREATE TABLE
- Создание API доступа к базам данных на языке Python для доступа
Question
иChoice
объектов.
Но сначала нам нужно сообщить нашему проекту, что polls
приложение установлено.
Философия
Приложения Django являются «подключаемыми»: вы можете использовать приложение в нескольких проектах, и вы можете распространять приложения, потому что они не должны быть привязаны к конкретной установке Django.
Чтобы включить приложение в наш проект, нам нужно добавить ссылку на его класс конфигурации в INSTALLED_APPS
параметр.
PollsConfig
Класс находится в polls/apps.py
файле, поэтому его пунктирный путь 'polls.apps.PollsConfig'
. Отредактируйте mysite/settings.py
файл и добавьте этот путь с точками к INSTALLED_APPS
настройке. Это будет выглядеть так:
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Теперь Django знает, как включить polls
приложение. Запустим еще одну команду:
$ python manage.py makemigrations polls
...\> py manage.py makemigrations polls
Вы должны увидеть что-то похожее на следующее:
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
Запустив makemigrations
, вы сообщаете Django, что вы внесли некоторые изменения в свои модели (в данном случае вы сделали новые) и что вы хотите, чтобы изменения были сохранены как миграция .
Миграции - это то, как Django сохраняет изменения в ваших моделях (и, следовательно, в вашей схеме базы данных) - это файлы на диске. Вы можете прочитать миграцию для вашей новой модели, если хотите; это файл polls/migrations/0001_initial.py
. Не волнуйтесь, от вас не ждут, что вы будете читать их каждый раз, когда Django создает их, но они предназначены для редактирования человеком на тот случай, если вы захотите вручную настроить, как Django меняет вещи.
Есть команда, которая будет запускать миграции за вас и автоматически управлять схемой вашей базы данных - она называется migrate
, и мы перейдем к ней через мгновение, - но сначала давайте посмотрим, какой SQL будет запускать эта миграция. Команда
sqlmigrate
берет имена миграции и возвращает их SQL:
$ python manage.py sqlmigrate polls 0001
...\> py manage.py sqlmigrate polls 0001
Вы должны увидеть что-то похожее на следующее (мы переформатировали его для удобства чтения):
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" (
"id" serial NOT NULL PRIMARY KEY,
"question_text" varchar(200) NOT NULL,
"pub_date" timestamp with time zone NOT NULL
);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" (
"id" serial NOT NULL PRIMARY KEY,
"choice_text" varchar(200) NOT NULL,
"votes" integer NOT NULL,
"question_id" integer NOT NULL
);
ALTER TABLE "polls_choice"
ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id"
FOREIGN KEY ("question_id")
REFERENCES "polls_question" ("id")
DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;
Обратите внимание на следующее:
- Точный результат будет зависеть от используемой базы данных. Приведенный выше пример создан для PostgreSQL.
- Имена таблиц генерируются автоматически путем объединения имени приложения (
polls
) и имени модели в нижнем регистре -question
иchoice
. (Вы можете изменить это поведение.) - Первичные ключи (ID) добавляются автоматически. (Вы также можете отменить это.)
- По соглашению Django добавляет
"_id"
к имени поля внешнего ключа. (Да, вы также можете отменить это.) - Связь внешнего ключа явно выражена
ограничением. Не беспокойтесь о деталях; он сообщает PostgreSQL не применять внешний ключ до конца транзакции.
FOREIGN KEY
DEFERRABLE
- Он адаптирован к используемой вами базе данных, поэтому типы полей для конкретной базы данных, такие как
auto_increment
(MySQL),serial
(PostgreSQL) или (SQLite), обрабатываются автоматически. То же самое касается цитирования имен полей - например, с использованием двойных или одинарных кавычек.integer primary key autoincrement
sqlmigrate
Команда не запустить миграцию базы данных - вместо этого, она выводит его на экран , так что вы можете увидеть , что думает SQL Django требуется. Это полезно для проверки того, что Django собирается делать, или если у вас есть администраторы баз данных, которым требуются сценарии SQL для внесения изменений.
Если вам интересно, вы также можете запустить
; это проверяет наличие каких-либо проблем в вашем проекте, не выполняя миграции или не касаясь базы данных.python manage.py check
Теперь запустите еще migrate
раз, чтобы создать эти таблицы моделей в своей базе данных:
$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
...\> py manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
Команда migrate
берет все миграции, которые не были применены (Django отслеживает, какие из них применяются, используя специальную таблицу в вашей базе данных, называемую django_migrations
), и запускает их в вашей базе данных - по сути, синхронизируя изменения, которые вы внесли в свои модели, со схемой в база данных.
Миграции очень эффективны и позволяют вам со временем изменять модели по мере разработки проекта без необходимости удалять базу данных или таблицы и создавать новые - он специализируется на обновлении вашей базы данных в реальном времени без потери данных. Мы рассмотрим их более подробно в более поздней части руководства, а пока запомните трехэтапное руководство по внесению изменений в модель:
- Измените свои модели (в
models.py
). - Запустите, чтобы создать миграции для этих изменений
python manage.py makemigrations
- Выполните, чтобы применить эти изменения к базе данных.
python manage.py migrate
Причина того, что существуют отдельные команды для выполнения и применения миграций, заключается в том, что вы фиксируете миграции в своей системе управления версиями и отправляете их вместе со своим приложением; они не только облегчают вашу разработку, но и могут использоваться другими разработчиками и в производственной среде.
Прочтите документацию django-admin для получения полной информации о возможностях этой manage.py
утилиты.
Играем с API ¶
Теперь давайте перейдем к интерактивной оболочке Python и поэкспериментируем с бесплатным API Django. Чтобы вызвать оболочку Python, используйте эту команду:
$ python manage.py shell
...\> py manage.py shell
Мы используем это вместо того, чтобы просто набирать «python», потому что manage.py
устанавливаетDJANGO_SETTINGS_MODULE
переменная среды, которая дает Django путь импорта Python к вашему mysite/settings.py
файлу.
Как только вы окажетесь в оболочке, изучите API базы данных :
>>> from polls.models import Choice, Question # Import the model classes we just wrote.
# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>
# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# Save the object into the database. You have to call save() explicitly.
>>> q.save()
# Now it has an ID.
>>> q.id
1
# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
Подождите минуту. не является полезным представлением этого объекта. Давайте исправим это, отредактировав модель (в файле) и добавив
метод к обоим и
:<Question: Question object (1)>
Question
polls/models.py
__str__()
Question
Choice
from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
Важно добавлять __str__()
методы в ваши модели не только для вашего удобства при работе с интерактивной подсказкой, но и потому, что представления объектов используются в автоматически сгенерированном админке Django.
Давайте также добавим в эту модель собственный метод:
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
Обратите внимание на добавление и для ссылки на стандартный модуль Python и утилиты Django, связанные с часовыми поясами , соответственно. Если вы не знакомы с обработкой часовых поясов в Python, вы можете узнать больше в документации по поддержке часовых поясов .import datetime
from django.utils import
timezone
datetime
django.utils.timezone
Сохраните эти изменения и запустите новую интерактивную оболочку Python, запустив еще
раз:python manage.py shell
>>> from polls.models import Choice, Question
# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>
# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>
# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>
# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()
Для получения дополнительной информации о связях модели см. Доступ к связанным объектам . Для получения дополнительной информации о том, как использовать двойное подчеркивание для поиска полей через API, см. Поиск полей . Полную информацию об API базы данных см. В нашей справке по API базы данных .
Представляем администратора Django ¶
Философия
Создание административных сайтов для ваших сотрудников или клиентов для добавления, изменения и удаления контента - утомительная работа, не требующая особого творчества. По этой причине Django полностью автоматизирует создание интерфейсов администратора для моделей.
Django был написан в среде редакции новостей с очень четким разделением между «издателями контента» и «общедоступным» сайтом. Менеджеры сайтов используют систему для добавления новостей, событий, спортивных результатов и т. Д., И этот контент отображается на общедоступном сайте. Django решает проблему создания единого интерфейса для администраторов сайта для редактирования контента.
Администратор не предназначен для использования посетителями сайта. Это для менеджеров сайтов.
Создание пользователя-администратора ¶
Сначала нам нужно создать пользователя, который сможет войти на сайт администратора. Выполните следующую команду:
$ python manage.py createsuperuser
...\> py manage.py createsuperuser
Введите желаемое имя пользователя и нажмите ввод.
Username: admin
Затем вам будет предложено ввести желаемый адрес электронной почты:
Email address: [email protected]
Последний шаг - ввести свой пароль. Вам будет предложено ввести пароль дважды, второй раз в качестве подтверждения первого.
Password: **********
Password (again): *********
Superuser created successfully.
Запустите сервер разработки ¶
Сайт администратора Django активирован по умолчанию. Давайте запустим сервер разработки и исследуем его.
Если сервер не работает, запустите его так:
$ python manage.py runserver
...\> py manage.py runserver
Теперь откройте веб-браузер и перейдите в «/ admin /» в локальном домене - например, http://127.0.0.1:8000/admin/ . Вы должны увидеть экран входа в систему администратора:
Поскольку перевод включен по умолчанию, если вы установите LANGUAGE_CODE
этот параметр, экран входа в систему будет отображаться на заданном языке (если у Django есть соответствующие переводы).
Войдите в админку ¶
Теперь попробуйте войти в систему с учетной записью суперпользователя, которую вы создали на предыдущем шаге. Вы должны увидеть страницу индекса администратора Django:
Вы должны увидеть несколько типов редактируемого контента: группы и пользователей. Они предоставляются django.contrib.auth
платформой аутентификации, поставляемой Django.
Сделайте приложение для голосования изменяемым в админке ¶
Но где наше приложение для опросов? Он не отображается на странице индекса администратора.
Осталось только одно: нам нужно сообщить администратору, что у Question
объектов есть интерфейс администратора. Для этого откройте polls/admin.py
файл и отредактируйте его так:
from django.contrib import admin
from .models import Question
admin.site.register(Question)
Ознакомьтесь с бесплатными функциями администратора ¶
Теперь, когда мы зарегистрировались Question
, Django знает, что он должен отображаться на странице индекса администратора:
Щелкните «Вопросы». Теперь вы находитесь на странице «списка изменений» для вопросов. На этой странице отображаются все вопросы из базы данных, и вы можете выбрать один из них, чтобы изменить его. Есть «Что случилось?» вопрос, который мы создали ранее:
Нажмите "Что случилось?" вопрос для редактирования:
Здесь следует отметить:
- Форма автоматически создается из
Question
модели. - Различные типы полей модели (
DateTimeField
,CharField
) соответствуют соответствующему виджету ввода HTML. Каждый тип поля умеет отображать себя в админке Django. - Каждый
DateTimeField
получает бесплатные ярлыки JavaScript. Даты получают ярлык «Сегодня» и всплывающее окно календаря, а время - ярлык «Сейчас» и удобное всплывающее окно со списком часто вводимого времени.
В нижней части страницы есть несколько вариантов:
- Сохранить - сохраняет изменения и возвращает на страницу списка изменений для этого типа объекта.
- Сохранить и продолжить редактирование - сохраняет изменения и перезагружает страницу администратора для этого объекта.
- Сохранить и добавить еще - сохраняет изменения и загружает новую пустую форму для этого типа объекта.
- Удалить - отображает страницу подтверждения удаления.
Если значение «Дата публикации» не совпадает со временем, когда вы создавали вопрос в Уроке 1 , это, вероятно, означает, что вы забыли установить правильное значение для TIME_ZONE
параметра. Измените его, перезагрузите страницу и убедитесь, что отображается правильное значение.
Измените «Дата публикации», щелкнув ярлыки «Сегодня» и «Сейчас». Затем нажмите «Сохранить и продолжить редактирование». Затем нажмите «История» в правом верхнем углу. Вы увидите страницу со списком всех изменений, внесенных в этот объект с помощью администратора Django, с отметкой времени и именем пользователя человека, который внес изменение:
Когда вы освоитесь с API моделей и познакомитесь с сайтом администратора, прочитайте часть 3 этого руководства, чтобы узнать, как добавить больше представлений в наше приложение для опросов.