Написание вашего первого приложения 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:

Эти приложения включены по умолчанию для удобства в общем случае.

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

$ python manage.py migrate
... \> py manage.py migrate

Команда migrateпросматривает INSTALLED_APPSнастройку и создает все необходимые таблицы базы данных в соответствии с настройками базы данных в вашем mysite/settings.pyфайле и миграциями базы данных, поставляемыми с приложением (мы рассмотрим их позже). Вы увидите сообщение для каждой применяемой миграции. Если вам интересно, запустите клиент командной строки для своей базы данных и введите \dt(PostgreSQL), (MariaDB, MySQL), (SQLite) или (Oracle), чтобы отобразить таблицы, созданные Django.SHOW TABLES;.schemaSELECT 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файл так, чтобы он выглядел так:

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значение votes0.

Наконец, обратите внимание, что связь определяется с помощью 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настройке. Это будет выглядеть так:

mysite / settings.py
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 KEYDEFERRABLE
  • Он адаптирован к используемой вами базе данных, поэтому типы полей для конкретной базы данных, такие как 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)>Questionpolls/models.py__str__()QuestionChoice

polls / models.py
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.

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

polls / models.py
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 datetimefrom django.utils import timezonedatetimedjango.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/ . Вы должны увидеть экран входа в систему администратора:

Экран входа администратора Django

Поскольку перевод включен по умолчанию, если вы установите LANGUAGE_CODEэтот параметр, экран входа в систему будет отображаться на заданном языке (если у Django есть соответствующие переводы).

Войдите в админку

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

Индексная страница администратора Django

Вы должны увидеть несколько типов редактируемого контента: группы и пользователей. Они предоставляются django.contrib.authплатформой аутентификации, поставляемой Django.

Сделайте приложение для голосования изменяемым в админке

Но где наше приложение для опросов? Он не отображается на странице индекса администратора.

Осталось только одно: нам нужно сообщить администратору, что у Questionобъектов есть интерфейс администратора. Для этого откройте polls/admin.pyфайл и отредактируйте его так:

опросы / admin.py
from django.contrib import admin

from .models import Question

admin.site.register(Question)

Ознакомьтесь с бесплатными функциями администратора

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

Индексная страница администратора Django, теперь с отображаемыми опросами

Щелкните «Вопросы». Теперь вы находитесь на странице «списка изменений» для вопросов. На этой странице отображаются все вопросы из базы данных, и вы можете выбрать один из них, чтобы изменить его. Есть «Что случилось?» вопрос, который мы создали ранее:

Страница списка изменений опросов

Нажмите "Что случилось?" вопрос для редактирования:

Форма редактирования объекта вопроса

Здесь следует отметить:

  • Форма автоматически создается из Questionмодели.
  • Различные типы полей модели ( DateTimeField, CharField) соответствуют соответствующему виджету ввода HTML. Каждый тип поля умеет отображать себя в админке Django.
  • Каждый DateTimeFieldполучает бесплатные ярлыки JavaScript. Даты получают ярлык «Сегодня» и всплывающее окно календаря, а время - ярлык «Сейчас» и удобное всплывающее окно со списком часто вводимого времени.

В нижней части страницы есть несколько вариантов:

  • Сохранить - сохраняет изменения и возвращает на страницу списка изменений для этого типа объекта.
  • Сохранить и продолжить редактирование - сохраняет изменения и перезагружает страницу администратора для этого объекта.
  • Сохранить и добавить еще - сохраняет изменения и загружает новую пустую форму для этого типа объекта.
  • Удалить - отображает страницу подтверждения удаления.

Если значение «Дата публикации» не совпадает со временем, когда вы создавали вопрос в Уроке 1 , это, вероятно, означает, что вы забыли установить правильное значение для TIME_ZONEпараметра. Измените его, перезагрузите страницу и убедитесь, что отображается правильное значение.

Измените «Дата публикации», щелкнув ярлыки «Сегодня» и «Сейчас». Затем нажмите «Сохранить и продолжить редактирование». Затем нажмите «История» в правом верхнем углу. Вы увидите страницу со списком всех изменений, внесенных в этот объект с помощью администратора Django, с отметкой времени и именем пользователя человека, который внес изменение:

Страница истории для объекта вопроса

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

Copyright ©2021 All rights reserved