← Проект 1 Веб-приложение на основе XLSX вместо базы данных ← Часть 1 Django — что это? Обзор и установка фреймворка, структура проекта
Для создания базы данных (и всех взаимодействий с ней) Django использует ORM (объектно-реляционное представление). ORM – это своеобразная прослойка, которая позволяет работать с базой данных, используя классы и методы вместо написания сложных SQL-запросов.
Вот основные возможности и преимущества использования ORM в Django:
Моделирование базы данных. Разработчик определяет структуру таблиц, их поля и взаимосвязи между ними с помощью специальных классов – моделей .
Отношения и связи. Связывание моделей различными типами отношений (один-к-одному, один-ко-многим и многие-ко-многим) в ORM выполняется очень просто.
Простой доступ к данным. Запросы к базе данных выполняются с помощью простого и понятного синтаксиса вместо языка SQL.
Гибкое обновление структуры базы данных. С помощью миграций ORM мгновенно изменяет структуру базы данных в соответствии с изменениями в моделях.
Автоматическая валидация данных. ORM предусматривает несколько способов автоматической валидации данных в соответствии с определенными правилами и ограничениями.
Защита от SQL-инъекций. Код SQL запроса определяется отдельно от параметров запроса.
Переносимость – можно легко переключаться между разными базами данных, не меняя код приложения.
Кеширование запросов для повышения производительности.
Разнообразная дополнительная функциональность – ORM предоставляет готовые решения для работы с данными: создание и изменение объектов, выборки, агрегации, пагинация и т.д. Не нужно все это программировать вручную.
Недостатки у ORM тоже есть, но их гораздо меньше, чем преимуществ:
Снижение производительности. ORM добавляет накладные расходы, так как создает дополнительный слой абстракции над базой данных. В некоторых случаях использование ORM может привести к уменьшению производительности из-за неоптимальных запросов.
Для написания сложных запросов (и для оптимизации часто повторяющихся, ресурсоемких операций) могут потребоваться Q и F-объекты .
В некоторых случаях сложные запросы нужно писать вручную на SQL .
? Библиотека питониста Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека питониста» ?? Библиотека собеса по Python Подтянуть свои знания по Python вы можете на нашем телеграм-канале «Библиотека собеса по Python» ?? Библиотека задач по Python» Интересные задачи по Python для практики можно найти на нашем телеграм-канале «Библиотека задач по Python»
Модели в Django
Модели в Django представляют собой классы Python, которые описывают структуру, свойства и взаимосвязи таблиц в базе данных. Модели не только играют ключевую роль в создании и управлении схемой базы данных, но также обеспечивают удобный интерфейс для работы с данными.
Модели содержат поля , которые представляют столбцы в таблице БД. Эти поля определяют тип данных, валидацию и другие свойства для хранения, извлечения и обновления данных. Например, поле типа CharField может описывать строковое значение, поле типа DateField – дату, а поле типа ForeignKey – отношение типа один-ко-многим между таблицами. Кроме полей, для модели можно определять метаданные, методы, менеджеры для выборки и фильтрации данных.
Связи между моделями
Основные типы связей между моделями – один-к-одному , один-ко-многим, многие-ко-многим . Рассмотрим на примерах.
Один-к-одном у (OneToOne) – это связь одной записи в одной таблице с одной записью в другой таблице. Например, один пользователь может иметь только один профиль:
class User(models.Model): name = models.CharField(max_length=50) class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) bio = models.TextField(blank=True) avatar = models.ImageField(upload_to='avatars/', blank=True)
Один-ко-многим (ForeignKey) – это связь одной записи в одной таблице со многими записями в другой. Например, один автор может написать несколько книг:
class Author(models.Model): name = models.CharField(max_length=50) class Book(models.Model): author = models.ForeignKey(Author, on_delete=models.CASCADE) title = models.CharField(max_length=50)
Многие-ко-многим (ManyToMany) – это связь между произвольным количеством записей в двух таблицах. Например, одна книга может принадлежать к нескольким жанрам сразу, а к одному жанру относится множество книг:
class Genre(models.Model): name = models.CharField(max_length=50) class Book(models.Model): title = models.CharField(max_length=50) genres = models.ManyToManyField(Genre)
Статья по теме ? Самоучитель по Python для начинающих. Часть 22: Основы работы с SQLite
Создание базы данных в Django
Для создания базы данных в Django нужно:
Создать первичную базу с помощью команды migrate .
Создать аккаунт суперпользователя (админа) командой createsuperuser .
Написать модели, определяющие нужную структуру БД.
Подготовить и выполнить миграции – makemigrations и migrate .
Выполним все эти действия шаг за шагом.
Инициализация базы данных
Django по умолчанию использует SQLite , и для подключения этой базы к приложению (в отличие от других баз типа MySQL и PostgreSQL ) не нужно делать никаких специальных настроек. Как только вы создали проект и приложение в нем, можно выполнить команду migrate
, что приведет к появлению базы данных db.sqlite3 на одном уровне с директорией приложения и файлом manage.py :
python -m venv myprojectvenv cd myproject venvscriptsactivate pip install django django-admin startproject config . python manage.py startapp myapp python manage.py migrate python manage.py createsuperuser
Структура проекта теперь выглядит так:
myproject |-- config | |-- __init__.py | |-- settings.py | |-- urls.py | `-- wsgi.py |-- myapp | |-- __init__.py | |-- admin.py | |-- apps.py | |-- models.py | |-- tests.py | |-- views.py | `-- migrations |-- venv |-- db.sqlite3 `-- manage.py
Добавьте приложение myapp в config/settings.py:
INSTALLED_APPS = [ 'myapp.apps.MyappConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
Создание структуры базы данных
Сохраните в файле myapp/models.py модели Author , Genre и Book :
from django.db import models class Author(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) biography = models.TextField(blank=True) class Genre(models.Model): name = models.CharField(max_length=50) description = models.TextField(blank=True) class Book(models.Model): title = models.CharField(max_length=100) description = models.TextField() publication_date = models.DateField() num_pages = models.IntegerField() price = models.DecimalField(max_digits=6, decimal_places=2) genres = models.ManyToManyField(Genre) author = models.ForeignKey(Author, on_delete=models.CASCADE) is_bestseller = models.BooleanField(default=False)
Теперь можно подготовить миграции (изменения в структуре) БД:
python manage.py migrate
И применить миграции к структуре БД:
python manage.py migrate
В базе данных появились соответствующие таблицы Author, Genre и Book . Вот какие значения там можно сохранять:
CharField – строка ограниченной длины, для небольших текстовых значений вроде имен и названий.
TextField – неограниченный текст, для мультистрочных текстов вроде подробных описаний.
DateField – дата, хранится в формате ГГГГ-ММ-ДД .
IntegerField – целочисленное значение.
DecimalField – число с плавающей точкой, для денежных значений. Это более точный формат, чем FloatField .
ForeignKey – ссылка на другую модель, связь один-ко-многим.
ManyToManyField – связь многие-ко-многим.
BooleanField – логическое значение True или False .
У моделей могут быть и другие поля – например, FileField для хранения ссылки на текстовый или аудиофайл книги, ImageField для ссылки на изображение обложки. Надо заметить, что файлы в базе данных обычно не хранят (хотя это возможно) – в соответствующих файлам полях сохраняются только ссылки на файлы , которые, в свою очередь, физически находятся в директории media и других служебных папках.
Статья по теме ?? Python + MySQL: как подключиться к СУБД MySQL и работать с ней с помощью Python
Регистрация моделей в панели управления Django
Чтобы с моделями можно было работать в админке Django, нужно их зарегистрировать в файле myapp/admin.py :
from django.contrib import admin from .models import Author, Genre, Book admin.site.register(Author) admin.site.register(Genre) admin.site.register(Book)
Это самый простой способ представления моделей в админке, есть и более удобные. Например, так можно обеспечить вывод полей Book прямо на странице Author :
from django.contrib import admin from .models import Author, Genre, Book class BookInline(admin.TabularInline): model = Book class AuthorAdmin(admin.ModelAdmin): inlines = [BookInline] admin.site.register(Author, AuthorAdmin) admin.site.register(Genre) admin.site.register(Book)
Теперь можно запустить сервер, зайти в админку и посмотреть на визуальное представление базы данных:
python manage.py runserver
Панель управления Django доступна по адресу http://127.0.0.1:8000/admin :
Панель управления Django доступна по адресу http://127.0.0.1:8000/admin
Класс Meta
Русскоязычные названия для моделей, порядок вывода записей, ограничения по уникальности и многое другое можно определить с помощью класса Meta :
class Author(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) biography = models.TextField(blank=True) class Meta: ordering = ['-id'] verbose_name = 'Автор' verbose_name_plural = 'Авторы' def __str__(self): return f'{self.first_name} {self.last_name}' class Genre(models.Model): name = models.CharField(max_length=50) description = models.TextField(blank=True) class Meta: verbose_name = 'Жанр' verbose_name_plural = 'Жанры' def __str__(self): return self.name class Book(models.Model): title = models.CharField(max_length=100) description = models.TextField() publication_date = models.DateField() num_pages = models.IntegerField() price = models.DecimalField(max_digits=6, decimal_places=2) genres = models.ManyToManyField(Genre) author = models.ForeignKey(Author, on_delete=models.CASCADE) is_bestseller = models.BooleanField(default=False) class Meta: ordering = ['-id'] verbose_name = 'Книга' verbose_name_plural = 'Книги' def __str__(self): return self.title
Статья по теме ?? Python и MySQL: практическое введение
Заполнение базы
Наполнить БД информацией можно несколькими способами:
Вручную в админке. Панель управления Django является, по сути, удобным визуальным GUI для CRUD-операций. Но записи придется вводить по одной.
В интерактивной оболочке (shell ) Django. Так можно ввести сколько угодно записей за раз, однако набирать их придется вручную, а после каждого неверного отступа процесс нужно будет начинать сначала. В shell также можно загрузить данные из файла, ниже мы рассмотрим этот способ.
С помощью команды loaddata и данных из заранее подготовленного json-файла, структура которого соответствует схеме БД.
С помощью Python-скрипта, который может загрузить данные из любого файла (json, csv, xlsx), придать им нужную структуру и сохранить в базе. Такие скрипты можно выполнять в shell и в cmd.
Самый удобный из этих способов – загрузка с loaddata :
Сначала нужно создать директорию fixtures в папке приложения, то есть myapp/fixtures .
В директорию fixtures нужно поместить готовый json-файл с данными.
После чего надо выполнить команду python manage.py loaddata data.json
.
python manage.py loaddata data.json Installed 9 object(s) from 1 fixture(s)
Запустите сервер, зайдите в админку – теперь там есть 3 жанра, 3 книги и 3 писателя:
В админке появились 3 жанра, 3 книги и 3 писателя
А так можно добавлять записи в БД в интерактивной оболочке Django:
python manage.py shell >>> from myapp.models import Author, Genre, Book >>> new_author = Author.objects.create(first_name='Дэн', last_name='Симмонс', biography='Современный американский писатель-фантаст') >>> print(Author.objects.all()) <QuerySet [<Author: Дэн Симмонс>, <Author: Джоан Роулинг>, <Author: Федор Достоевский>, <Author: Лев Толстой>]> >>> new_genre = Genre.objects.create(name='Триллер', description='В литературных произведениях этого жанра есть загадка и ощущение тревоги или страха.') >>> print(Genre.objects.all()) <QuerySet [<Genre: Роман>, <Genre: Повесть>, <Genre: Фантастика>, <Genre: Триллер>]> >>> new_book = Book.objects.create(title='Террор', description='Фантастическая версия трагической гибели арктической экспедиции Джона Франклина.', publication_date='2007-01-09', num_pages=1002, price=970.00, author=new_author, is_bestseller=True) >>> new_book.genres.add(new_genre)
Результат – в базу добавлены записи о писателе Дэне Симмонсе, его книге «Террор», и одном из жанров, к которым относится эта книга – триллер:
В базу добавлены записи о писателе Дэне Симмонсе, его книге «Террор»
Еще один способ – загрузка данных из скрипта, выполненного в shell:
Сохраните скрипт add_data.py на одном уровне с manage.py .
Запустите оболочку командой python manage.py shell
.
Выполните команду exec(open("add_data.py", encoding="utf-8").read())
.
Готово – в базе данных появились записи о двух новых авторах, книгах и жанрах:
В базе данных появились записи о двух новых авторах, книгах и жанрах Статья по теме ?? Пишем гибридное приложение для хранения заметок на Django, Django Ninja REST Framework и Alpine.js
Получение данных из БД
Все основные манипуляции с данными в Django происходят в представлениях , которые находятся в файле views.py . Представления делятся на функциональные и классовые . Представления на основе классов имеют несколько весомых преимуществ по сравнению с функциональными, и в дальнейшем мы подробно их рассмотрим.
Сохраните эти функциональные представления в myapp/views.py:
from django.shortcuts import render from .models import Author, Book, Genre def authors(request): authors = Author.objects.all() context = { 'authors': authors } return render(request, 'authors.html', context) def books(request): books = Book.objects.all() context = { 'books': books } return render(request, 'books.html', context) def genres(request): genres = Genre.objects.all() context = { 'genres': genres } return render(request, 'genres.html', context)
Представления передают в шаблоны все записи об авторах, книгах и жанрах. В действие эти представления приводят маршруты. Сохраните эти маршруты в файле myapp/urls.py:
from django.urls import path from .views import authors, books, genres urlpatterns = [ path('authors/', authors, name='authors'), path('books/', books, name='books'), path('genres/', genres, name='genres') ]
И добавьте маршруты myapp в config/urls.py:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('myapp.urls')), ]
Теперь нужно создать директорию templates внутри myapp и сохранить в ней эти шаблоны:
base.html
authors.html
books.html
genres.html
Все готово – запускайте сервер, переходите по ссылкам-маршрутам:
http://127.0.0.1:8000/authors/
http://127.0.0.1:8000/books/
http://127.0.0.1:8000/genres/
http://127.0.0.1:8000/authors/
http://127.0.0.1:8000/books/
http://127.0.0.1:8000/genres/
Подведем итоги
Мы рассмотрели:
Принцип создания базы данных с помощью моделей ORM .
Способы заполнения БД с использованием loaddata , команды create() и скрипта, запускаемого в интерактивной оболочке shell .
Простейшие представления на основе функций.
Механизм передачи данных из БД на фронтенд.
Представления могут выполнять гораздо более сложные манипуляции с данными, чем передачу в шаблоны всех существующих в базе записей. Со всеми возможностями представлений мы разберемся в последующих главах и курсовых проектах.
Весь код и база данных, использованные в этой статье, находятся здесь.
***
Содержание курса
Часть 1: Django — что это? Обзор и установка фреймворка, структура проекта
Проект 1: Веб-приложение на основе XLSX вместо базы данных
Часть 2: ORM и основы работы с базами данных