Особенности Django: модели, администрирование и использование реляционной базы данных (часть 3)
Опубликовано: 2022-03-10Прежде чем мы начнем, я хочу отметить, что встроенные административные возможности Django, даже после настройки, не предназначены для конечных пользователей. Панель администратора существует как инструмент разработчика, оператора и администратора для создания и обслуживания программного обеспечения. Он не предназначен для предоставления конечным пользователям возможностей модерации или каких-либо других возможностей администратора на платформе, которую вы разрабатываете.
Эта статья основана на гипотезе, состоящей из двух частей:
- Панель администратора Django настолько интуитивно понятна, что вы уже знаете, как ею пользоваться.
- Панель администратора Django настолько мощна, что мы можем использовать ее как инструмент для изучения представления данных в реляционной базе данных с использованием модели Django.
Я предлагаю эти идеи с оговоркой, что нам все еще нужно будет написать некоторый код конфигурации, чтобы активировать более мощные возможности панели администратора, и нам все еще нужно будет использовать ORM на основе моделей Django (объектно-реляционное сопоставление), чтобы указать представление данных в нашей системе.
Рекомендуемое чтение
«Django Highlights» — это серия, знакомящая с важными концепциями веб-разработки в Django. Возможно, вы захотите прочитать о предоставлении безопасных потоков аутентификации пользователей и следовать демонстрации использования шаблонов Django для написания сложных страниц.
Настройка
В этой статье мы будем работать с примером проекта. Проект моделирует некоторые данные, которые библиотека будет хранить о своих книгах и посетителях. Пример должен быть применим ко многим типам систем, которые управляют пользователями и/или запасами. Вот краткий обзор того, как выглядят данные:
Выполните следующие шаги, чтобы запустить пример кода на локальном компьютере.
1. Установка пакетов
С установленным Python 3.6 или выше создайте каталог и виртуальную среду. Затем установите следующие пакеты:
pip install django django-grappelli
Django — это веб-фреймворк, с которым мы работаем в этой статье. ( django-grappelli
— это тема панели администратора, которую мы кратко рассмотрим.)
2. Получение проекта
После установки предыдущих пакетов загрузите пример кода с GitHub. Бегать:
git clone https://github.com/philipkiely/library_records.git cd library_records/library
3. Создание суперпользователя
Используя следующие команды, настройте базу данных и создайте суперпользователя. Интерфейс командной строки проведет вас через процесс создания суперпользователя. Ваша учетная запись суперпользователя будет использоваться для доступа к панели администратора через мгновение, поэтому обязательно запомните установленный вами пароль. Использовать:
python manage.py migrate python manage.py createsuperuser
4. Загрузка данных
Для нашего исследования я создал набор данных под названием фикстура, которую вы можете загрузить в базу данных (подробнее о том, как создать фикстуру, читайте в конце статьи). Используйте прибор для заполнения вашей базы данных, прежде чем исследовать ее в панели администратора. Бегать:
python manage.py loaddata ../fixture.json
5. Запуск примера проекта
Наконец, вы готовы запустить пример кода. Для запуска сервера используйте следующую команду:
python manage.py runserver
Откройте в браузере https://127.0.0.1:8000, чтобы просмотреть проект. Обратите внимание, что вы автоматически перенаправляетесь в панель администратора по адресу /admin/ . Я сделал это со следующей конфигурацией в library/urls.py :
from django.contrib import admin from django.urls import path from records import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index), ]
в сочетании со следующим простым перенаправлением в records/views.py :
from django.http import HttpResponseRedirect def index(request): return HttpResponseRedirect('/admin/')
Использование панели администратора
Мы сделали это! Когда вы загружаете свою страницу, вы должны увидеть что-то вроде следующего:
Это представление реализуется с помощью следующего стандартного кода в records/admin.py :
from django.contrib import admin from .models import Book, Patron, Copy admin.site.register(Book) admin.site.register(Copy) admin.site.register(Patron)
Это представление должно дать вам начальное представление о данных, которые хранит система. Я развею некоторые тайны: Groups
и Users
определяются Django и хранят информацию и разрешения для учетных записей в системе. Подробнее о модели User
можно прочитать в одной из предыдущих статей этой серии. Books
, Copys
и Patrons
— это таблицы в базе данных, которые мы создали при выполнении миграций и которые заполняются путем загрузки фикстуры. Обратите внимание, что Django наивно использует имена моделей во множественном числе, добавляя «s», даже в таких случаях, как «copy», где это неправильное написание.
В нашем проекте Book
— это запись с названием, автором, датой публикации и ISBN (международный стандартный номер книги). Библиотека поддерживает Copy
каждой Book
или, возможно, несколько. Каждая Copy
может быть проверена Patron
или может быть зарегистрирована в данный момент. Patron
— это расширение User
, которое записывает его адрес и дату рождения.
Создать, прочитать, обновить, уничтожить
Одной из стандартных возможностей панели администратора является добавление экземпляров каждой модели. Нажмите «книги», чтобы перейти на страницу модели, и нажмите кнопку «Добавить книгу» в правом верхнем углу. При этом появится форма, которую вы можете заполнить и сохранить, чтобы создать книгу.
Создание Patron
раскрывает еще одну встроенную возможность формы создания администратора: вы можете создать подключенную модель непосредственно из той же формы. На снимке экрана ниже показано всплывающее окно, которое вызывается зеленым знаком «плюс» справа от раскрывающегося списка « User
». Таким образом, вы можете создать обе модели на одной странице администратора.
Вы можете создать COPY
с помощью того же механизма.
Для каждой записи вы можете щелкнуть строку, чтобы отредактировать ее, используя ту же форму. Вы также можете удалить записи с помощью действия администратора.
Действия администратора
Хотя встроенные возможности панели администратора очень полезны, вы можете создавать свои собственные инструменты, используя действия администратора. Мы создадим два: один для создания копий книг и один для возврата книг, которые были возвращены в библиотеку.
Чтобы создать Copy
Book
, перейдите по URL-адресу /admin/records/book/
и в раскрывающемся меню «Действие» выберите «Добавить копию книги (книг)», а затем установите флажки в левом столбце. из таблицы, чтобы выбрать, какую книгу или книги добавить в инвентарь.
Создание этого основано на методе модели, который мы рассмотрим позже. Мы можем вызвать это как действие администратора, создав класс ModelAdmin
для модели Profile
следующим образом в records/admin.py :
from django.contrib import admin from .models import Book, Patron, Copy class BookAdmin(admin.ModelAdmin): list_display = ("title", "author", "published") actions = ["make_copys"] def make_copys(self, request, queryset): for q in queryset: q.make_copy() self.message_user(request, "copy(s) created") make_copys.short_description = "Add a copy of book(s)" admin.site.register(Book, BookAdmin)
Свойство list_display
, какие поля используются для представления модели на странице обзора модели. Свойство actions
перечисляет действия администратора. Наше действие администратора определяется как функция внутри BookAdmin
и принимает три аргумента: сам объект администратора, запрос (фактический HTTP-запрос, отправленный клиентом) и набор запросов (список объектов, для которых были отмечены флажки). Мы выполняем одно и то же действие над каждым элементом в наборе запросов, а затем уведомляем пользователя о том, что действия выполнены. Каждое действие администратора требует краткого описания, чтобы его можно было правильно идентифицировать в раскрывающемся меню. Наконец, теперь мы добавляем BookAdmin
при регистрации модели.
Написание действий администратора для массовой настройки свойств довольно часто повторяется. Вот код для проверки Copy
, обратите внимание на то, что он почти эквивалентен предыдущему действию.
from django.contrib import admin from .models import Book, Patron, Copy class CopyAdmin(admin.ModelAdmin): actions = ["check_in_copys"] def check_in_copys(self, request, queryset): for q in queryset: q.check_in() self.message_user(request, "copy(s) checked in") check_in_copys.short_description = "Check in copy(s)" admin.site.register(Copy, CopyAdmin)
Тема администратора
По умолчанию Django предоставляет довольно простые стили для панели администратора. Вы можете создать свою собственную тему или использовать стороннюю тему, чтобы придать панели администратора новый вид. Одной из популярных тем с открытым исходным кодом является grappelli, которую мы установили ранее в этой статье. Вы можете ознакомиться с документацией, чтобы узнать обо всех его возможностях.
Установка темы довольно проста, для этого требуется всего две строки. Во-первых, добавьте grappelli
в INSTALLED_APPS
следующим образом в library/settings.py :
INSTALLED_APPS = [ 'grappelli', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'records', ]
Затем настройте library/urls.py :
from django.contrib import admin from django.urls import path, include from records import views urlpatterns = [ path('grappelli/', include('grappelli.urls')), path('admin/', admin.site.urls), path('', views.index), ]
После внесения этих изменений панель администратора должна выглядеть следующим образом:
Есть ряд других тем, и опять же вы можете разработать свою собственную. Я буду придерживаться стиля по умолчанию до конца этой статьи.
Понимание моделей
Теперь, когда вы освоились с панелью администратора и используете ее для навигации по данным, давайте взглянем на модели, которые определяют структуру нашей базы данных. Каждая модель представляет одну таблицу в реляционной базе данных.
Реляционная база данных хранит данные в одной или нескольких таблицах. Каждая из этих таблиц имеет определенную структуру столбцов, включая первичный ключ (уникальный идентификатор для каждого элемента) и один или несколько столбцов значений различных типов, таких как строки, целые числа и даты. Каждый объект, хранящийся в базе данных, представлен в виде одной строки. «Реляционная» часть названия происходит от того, что, возможно, является самой важной особенностью технологии: создание отношений между таблицами. Объект (строка) может иметь сопоставление «один к одному», «один ко многим» (внешний ключ) или «многие ко многим» со строками в других таблицах. Мы обсудим это далее в примерах.
Django по умолчанию использует SQLite3 для разработки. SQLite3 — это простой механизм реляционной базы данных, и ваша база данных автоматически создается как db.sqlite3 при первом запуске python manage.py migrate
. В этой статье мы продолжим использовать SQLite3, но он не подходит для использования в производственной среде, в первую очередь потому, что возможна перезапись при одновременном подключении пользователей. В производственной среде или при написании системы, которую вы когда-нибудь собираетесь развернуть, используйте PostgreSQL или MySQL.
Django использует модели для взаимодействия с базой данных. Используя часть ORM Django, файл records/models.py включает в себя несколько моделей, что позволяет указывать поля, свойства и методы для каждого объекта. При создании моделей мы стремимся к архитектуре «толстой модели», в разумных пределах. Это означает, что как можно больше проверки данных, синтаксического анализа, обработки, бизнес-логики, обработки исключений, разрешения пограничных случаев и подобных задач должно выполняться в спецификации самой модели. Под капотом модели Django представляют собой очень сложные многофункциональные объекты с очень полезным поведением по умолчанию. Это позволяет легко реализовать архитектуру «толстой модели» даже без написания значительного объема кода.
Давайте рассмотрим три модели в нашем примере приложения. Мы не можем охватить все, так как это должна быть вводная статья, а не полная документация по фреймворку Django, но я выделю наиболее важные варианты, которые я сделал при построении этих простых моделей.
Класс Book
— самая простая из моделей. Вот это из records/models.py :
from django.db import models class Book(models.Model): title = models.CharField(max_length=300) author = models.CharField(max_length=150) published = models.DateField() isbn = models.IntegerField(unique=True) def __str__(self): return self.title + " by " + self.author def make_copy(self): Copy.objects.create(book=self)
Для всех полей CharField
требуется указанный атрибут max_length
. Обычная длина — 150 символов, которую я удваиваю для title
в случае очень длинных заголовков. Конечно, все еще существует произвольный предел, который может быть превышен. Для неограниченной длины текста используйте TextField
. published
поле представляет собой DateField
. Время публикации книги не имеет значения, но если бы это было так, я бы использовал DateTimeField
. Наконец, ISBN — это целое число (ISBN — это 10 или 13 цифр, и поэтому все они соответствуют максимальному целочисленному значению), и мы используем unique=True
, поскольку никакие две книги не могут иметь одинаковый ISBN, который затем применяется на уровне базы данных.
Все объекты имеют метод __str__(self)
, определяющий их строковое представление. Мы переопределяем реализацию по умолчанию, предоставляемую классом models.Model
, и вместо этого представляем книги как «название по автору» во всех местах, где модель будет представлена в виде строки. Напомним, что ранее мы использовали list_display
в объекте администратора Book
, чтобы определить, какие поля будут отображаться в списке панели администратора. Если этот list_display
отсутствует, в списке администратора вместо этого отображается строковое представление модели, как и для Patron
и Copy
.
Наконец, у нас есть метод для Book
, который мы вызвали в его действии администратора, которое мы написали ранее. Эта функция создает Copy
, связанную с данным экземпляром Book
в базе данных.
Переходя к Patron
, эта модель вводит концепцию отношений один к одному, в данном случае со встроенной моделью User
. Проверьте это из records/models.py :
from django.db import models from django.contrib.auth.models import User class Patron(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) address = models.CharField(max_length=150) dob = models.DateField() def __str__(self): return self.user.username
Поле user
не совсем биективная функция. МОЖЕТ быть экземпляр User
без связанного с ним экземпляра Patron
. Однако User
НЕ МОЖЕТ быть связан более чем с одним экземпляром Patron
, а Patron
не может существовать только без одного отношения к пользователю. Это обеспечивается на уровне базы данных и гарантируется on_delete=models.CASCADE
: если экземпляр User
удален, связанный с ним Profile
будет удален.
Другие поля и __str__(self)
мы уже видели. Стоит отметить, что вы можете использовать отношение один к одному для получения атрибутов, в данном случае user.username
, в функциях модели.
Чтобы расширить полезность отношений с базой данных, давайте обратим внимание на Copy
from records/models.py :
from django.db import models class Copy(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) out_to = models.ForeignKey(Patron, blank=True, null=True, on_delete=models.SET_NULL) def __str__(self): has_copy = "checked in" if self.out_to: has_copy = self.out_to.user.username return self.book.title + " -> " + has_copy def check_out(self, p): self.out_to = p self.save() def check_in(self): self.out_to = None self.save()
Опять же, мы видели большую часть этого раньше, так что давайте сосредоточимся на новых вещах: models.ForeignKey
. Copy
должна принадлежать одной Book
, но в библиотеке может быть несколько Copy
каждой Book
. Book
может существовать в базе данных без Copy
библиотеки в своем каталоге, но Copy
не может существовать без базовой Book
.
Эта сложная взаимосвязь выражается следующей строкой:
book = models.ForeignKey(Book, on_delete=models.CASCADE)
Поведение при удалении такое же, как и у Patron
в отношении User
.
Отношения между Copy
и Patron
немного отличаются. Copy
может быть выдана не более чем одному Patron
, но каждый Patron
может выдать столько Copy
, сколько позволяет им библиотека. Однако это не постоянная связь, Copy
иногда не проверяется. Patron
и Copy
существуют в базе данных независимо друг от друга; удаление экземпляра одного не должно удалять экземпляр другого.
Это отношение по-прежнему используется для внешнего ключа, но с другими аргументами:
out_to = models.ForeignKey(Patron, blank=True, null=True, on_delete=models.SET_NULL)
Здесь наличие blank=True
позволяет формам принимать None
в качестве значения для отношения, а null=True
позволяет столбцу для отношения Patron
в таблице Copy
в базе данных принимать null
в качестве значения. Поведение при удалении, которое будет инициировано для Copy
, если экземпляр Patron
будет удален, когда эта Copy
извлечена, состоит в том, чтобы разорвать связь, оставив Copy
нетронутой, установив для поля Patron
значение null.
Один и тот же тип поля, models.ForeignKey
, может выражать очень разные отношения между объектами. Единственное отношение, которое я не смог точно вписать в пример, — это поле «многие ко многим», которое похоже на поле «один к одному», за исключением того, что, как следует из его названия, каждый экземпляр может быть связан со многими другими экземплярами. и каждый другой и каждый из них может быть связан со многими другими, например, как у книги может быть несколько авторов, каждый из которых написал несколько книг.
Миграции
Вам может быть интересно, как база данных узнает, что выражено в модели. По моему опыту, миграции — это одна из тех вещей, которые довольно просты, пока они не станут таковыми, а затем они съедят ваше лицо. Вот как сохранить свою кружку нетронутой для начинающих: узнайте о миграции и о том, как с ней взаимодействовать, но старайтесь избегать ручного редактирования файлов миграции. Если вы уже знаете, что делаете, пропустите этот раздел и продолжайте в том же духе.
В любом случае, ознакомьтесь с официальной документацией для полного рассмотрения вопроса.
Миграции переводят изменения в модели в изменения в схеме базы данных. Вам не нужно писать их самостоятельно, Django создает их с помощью команды python manage.py makemigrations
. Вы должны запускать эту команду, когда создаете новую модель или редактируете поля существующей модели, но нет необходимости делать это при создании или редактировании методов модели. Важно отметить, что миграции существуют в виде цепочки, каждая из которых ссылается на предыдущую, чтобы можно было вносить безошибочные изменения в схему базы данных. Таким образом, если вы совместно работаете над проектом, важно сохранить единую непротиворечивую историю миграции в системе контроля версий. При наличии непримененных миграций запустите python manage.py migrate
, чтобы применить их перед запуском сервера.
Пример проекта распространяется с одной миграцией, records/migrations/0001_initial.py . Опять же, это автоматически сгенерированный код, который вам не нужно редактировать, поэтому я не буду копировать его сюда, но если вы хотите получить представление о том, что происходит за кулисами, взгляните на него.
Светильники
В отличие от миграций, фикстуры не являются обычным аспектом разработки Django. Я использую их для распространения демонстрационных данных со статьями и никогда не использовал их для других целей. Однако, поскольку мы уже использовали один из них ранее, я чувствую себя обязанным представить тему.
На этот раз официальная документация немного скудна по этой теме. В целом, вы должны знать, что фикстуры — это способ импорта и экспорта данных из вашей базы данных в различных форматах, включая JSON, который я использую. Эта функция в основном предназначена для помощи в таких вещах, как автоматическое тестирование, и не является системой резервного копирования или способом редактирования данных в действующей базе данных. Кроме того, фикстуры не обновляются при миграции, и если вы попытаетесь применить фикстуру к базе данных с несовместимой схемой, произойдет сбой.
Чтобы сгенерировать фикстуру для всей базы данных, запустите:
python manage.py dumpdata --format json > fixture.json
Чтобы загрузить прибор, запустите:
python manage.py loaddata fixture.json
Заключение
Написание моделей в Django — огромная тема, а использование админки — другая. В 3000 слов мне удалось только представить каждое. Надеемся, что использование панели администратора дало вам лучший интерфейс для изучения того, как модели работают и взаимодействуют друг с другом, что дает вам уверенность в экспериментах и разработке собственных реляционных представлений данных.
Если вы ищете, с чего начать, попробуйте добавить модель Librarian
, которая наследуется от User
, как это делает Profile
. Чтобы усложнить задачу, попробуйте создать историю покупок для каждого Copy
и/или Patron
(есть несколько способов сделать это).
Django Highlights — это серия, знакомящая с важными концепциями веб-разработки в Django. Каждая статья написана как отдельное руководство по одному из аспектов разработки Django, призванное помочь фронтенд-разработчикам и дизайнерам глубже понять «другую половину» кодовой базы. Эти статьи в основном созданы, чтобы помочь вам понять теорию и соглашения, но содержат некоторые примеры кода, написанные на Django 3.0.
Дальнейшее чтение
Вам могут быть интересны следующие статьи и документация.
- Особенности Django: пользовательские модели и аутентификация (часть 1)
- Django Highlights: создание шаблонов строк сохранения (часть 2)
- Основные моменты Django: работа со статическими активами и медиафайлами (часть 4)
- Документация администратора Django
- Джанго Модели
- Справочник по полям модели Django
- Джанго Миграции