📖 Теория: конспект Django-блока (Уроки 13–24)
⚡ Краткий конспект
- __str__ — читаемое представление объекта в admin, логах и консоли.
- Meta — управляет таблицей (db_table), сортировкой (ordering), именами (verbose_name), уникальностью (unique_together) и индексами (indexes).
- ModelAdmin — list_display, search_fields, list_filter, ordering, fields, list_per_page, actions.
- Инлайны — TabularInline (таблица) / StackedInline (вертикаль). extra = количество пустых форм.
- User — django.contrib.auth.models.User. Кастомная: AbstractBaseUser + PermissionsMixin + AUTH_USER_MODEL.
- ORM-менеджер — Model.objects. create/save, all/filter/get/exclude, update/delete, Q, F, bulk_create/bulk_update.
- Shell —
python manage.py shell, затем импорт моделей.
1. Метод __str__ и класс Meta
Метод __str__
Определяет строковое представление объекта модели. Используется в admin-панели, Django Shell и в логах. Без него объекты отображаются как Book object (1).
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()
def __str__(self):
return f"{self.title} by {self.author}"
Преимущества __str__
- Удобное отображение в административной панели
- Читаемость в консольных выводах и Django Shell
- Улучшение читаемости логов и сообщений об ошибках
Класс Meta
Позволяет добавлять метаданные к модели: управлять именем таблицы, порядком сортировки, читаемыми именами, уникальностью и индексами.
| Атрибут | Описание | Пример |
|---|---|---|
db_table | Имя таблицы в БД | 'library_book' |
ordering | Порядок сортировки записей | ['-published_date'] |
verbose_name | Читаемое имя модели (ед. ч.) | 'fiction book' |
verbose_name_plural | Читаемое имя модели (мн. ч.) | 'fiction books' |
get_latest_by | Поле для latest()/earliest() | 'published_date' |
default_related_name | Имя обратной связи для FK | 'books' |
unique_together | Уникальность по комбинации полей | ('title', 'author') |
indexes | Список индексов | см. ниже |
constraints | Ограничения уровня БД | UniqueConstraint |
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
published_date = models.DateField()
class Meta:
db_table = 'library_book'
ordering = ['-published_date']
verbose_name = 'fiction book'
verbose_name_plural = 'fiction books'
unique_together = ('title', 'author')
get_latest_by = 'published_date'
indexes = [
models.Index(fields=['title', 'author']),
models.Index(fields=['published_date'], name='published_idx'),
]
2. Административная панель Django
Django Admin — встроенный CRUD-интерфейс для моделей. Доступен по адресу /admin/. Автоматически генерирует страницы создания, чтения, обновления и удаления объектов.
Два способа регистрации модели
# Способ 1: admin.site.register
from django.contrib import admin
from .models import Book
admin.site.register(Book) # простая регистрация
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date')
search_fields = ('title', 'author__name')
list_filter = ('author', 'published_date')
ordering = ('-author', 'title')
fields = ('author', 'title', 'published_date')
list_per_page = 2
admin.site.register(Book, BookAdmin)
# Способ 2: декоратор @admin.register
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'published_date')
search_fields = ('title', 'author')
list_filter = ('author', 'published_date')
ordering = ('-author', 'title')
list_per_page = 2
Ключевые атрибуты ModelAdmin
| Атрибут | Назначение |
|---|---|
list_display | Поля в списке объектов |
search_fields | Поля для полнотекстового поиска |
list_filter | Боковые фильтры |
ordering | Порядок сортировки в admin |
fields | Набор полей в форме редактирования |
list_per_page | Количество объектов на странице |
actions | Список пользовательских действий |
inlines | Список инлайн-форм |
Пользовательские действия (actions)
from django.contrib import admin
from django.utils import timezone
from .models import Book
def update_created_at(modeladmin, request, queryset):
queryset.update(created_at=timezone.now())
update_created_at.short_description = "Update created_at to current time"
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'publisher', 'published_date', 'created_at')
actions = [update_created_at]
3. Инлайн-формы
Инлайн-формы позволяют редактировать связанные объекты прямо на странице основной модели. Полезны для связей «один-ко-многим» (ForeignKey).
| Класс | Формат | Когда использовать |
|---|---|---|
TabularInline | Табличный (горизонтальный) | Много объектов, мало полей |
StackedInline | Вертикальный (карточками) | Объекты с большим числом полей |
from django.contrib import admin
from .models import Book, Publisher
class BookInline(admin.TabularInline): # или StackedInline
model = Book
extra = 1 # количество пустых форм для новых объектов
class PublisherAdmin(admin.ModelAdmin):
inlines = [BookInline]
admin.site.register(Publisher, PublisherAdmin)
admin.site.register(Book)
4. Модель User
Django предоставляет встроенную модель User из django.contrib.auth.models. Содержит все необходимые поля и методы для аутентификации.
Поля модели User
| Поле | Тип | Описание |
|---|---|---|
username | CharField (150) | Уникальный идентификатор. Обязательный |
password | CharField | Хэшированный пароль. Обязательный |
email | EmailField | Адрес e-mail. Необязательный |
first_name | CharField | Имя пользователя. Необязательный |
last_name | CharField | Фамилия. Необязательный |
is_staff | BooleanField | Доступ в admin. По умолчанию False |
is_active | BooleanField | Активный аккаунт. По умолчанию True |
is_superuser | BooleanField | Все права. По умолчанию False |
last_login | DateTimeField | Дата последнего входа. Может быть null |
date_joined | DateTimeField | Дата регистрации |
Иерархия наследования User
- AbstractBaseUser — базовый класс: поля password, last_login; методы set_password(), check_password(), get_session_auth_hash().
- PermissionsMixin — поля is_superuser, groups, user_permissions; методы has_perm(), has_perms(), has_module_perms().
- AbstractUser — полная реализация с username, email, first_name и т.д. Наследуется от AbstractBaseUser + PermissionsMixin.
- User — финальный класс, наследующийся от AbstractUser. Используется «из коробки».
Кастомная модель User
# models.py
from django.utils import timezone
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin, UserManager
from django.utils.translation import gettext_lazy as _
from django.db import models
class CustomUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=30, blank=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(default=timezone.now)
birth_date = models.DateField(null=True, blank=True)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email', 'birth_date']
def __str__(self):
return self.email
# settings.py
AUTH_USER_MODEL = 'myapp.CustomUser'
5. Django ORM — запросы
Менеджер моделей
Каждая модель Django имеет менеджер по умолчанию — objects. Через него выполняются все запросы к БД.
Создание записей
# Метод create() — создаёт и сохраняет в одном шаге
new_book = Book.objects.create(
title="The Great Gatsby",
author="F. Scott Fitzgerald",
published_date="1925-04-10"
)
# Метод save() — создаём объект, меняем, сохраняем
book = Book(title="1984", author="George Orwell", published_date="1949-06-08")
book.title = "Nineteen Eighty-Four"
book.save()
Чтение записей
# QuerySet — набор записей, поддерживает цепочки методов
all_books = Book.objects.all()
first_book = Book.objects.all().first() # первая или None
last_book = Book.objects.all().last() # последняя или None
count = Book.objects.all().count() # количество
exists = Book.objects.all().exists() # True / False
values = Book.objects.all().values('title', 'author') # список словарей
Метод get()
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
try:
book = Book.objects.get(title="The Great Gatsby")
except ObjectDoesNotExist:
print("Книга не найдена.")
except MultipleObjectsReturned:
print("Найдено несколько книг.")
Фильтры и Lookups
| Lookup | Описание | Пример |
|---|---|---|
exact | Точное совпадение | title__exact="1984" |
iexact | Без учёта регистра | title__iexact="1984" |
contains | Содержит подстроку | title__contains="Gatsby" |
icontains | Содержит (регистронезависимо) | title__icontains="gatsby" |
in | Входит в список | id__in=[1, 2, 3] |
gt / gte | Больше / больше или равно | published_date__gt="2000-01-01" |
lt / lte | Меньше / меньше или равно | price__lt=20 |
isnull | Является NULL | published_date__isnull=True |
startswith | Начинается с | title__startswith="The" |
endswith | Заканчивается на | title__endswith="ing" |
range | В диапазоне (включительно) | published_date__range=["2020-01-01","2023-01-01"] |
Класс Q — сложные условия
from django.db.models import Q
# OR
books = Book.objects.filter(Q(is_bestseller=True) | Q(published_date__gt="2000-01-01"))
# AND
books = Book.objects.filter(Q(is_bestseller=True) & Q(published_date__gt="2000-01-01"))
# NOT
books = Book.objects.filter(~Q(is_bestseller=True))
# Комбинированное
books = Book.objects.filter(
(Q(is_bestseller=True) | Q(published_date__gt="2000-01-01")) & ~Q(author="George Orwell")
)
Класс F — операции над полями
from django.db.models import F
# Увеличить цену всех книг на 10%
Book.objects.update(price=F('price') * 1.10)
# Скопировать значение поля со скидкой
Book.objects.update(discounted_price=F('price') * 0.9)
# Фильтр: книги, у которых discounted_price < price
books = Book.objects.filter(discounted_price__lt=F('price'))
Обновление и удаление
# Обновление одной записи через save()
book = Book.objects.get(id=1)
book.title = "New Title"
book.save()
# Массовое обновление через update()
Book.objects.filter(author="F. Scott Fitzgerald").update(price=9.99)
# Удаление одной записи
book = Book.objects.get(id=1)
book.delete()
# Удаление нескольких записей
deleted_count, _ = Book.objects.filter(author="F. Scott Fitzgerald").delete()
Bulk-операции
from decimal import Decimal
# bulk_create — одним SQL-запросом
books = [
Book(title="Book 1", author="Author 1", published_date="2021-01-01", price=12.99),
Book(title="Book 2", author="Author 2", published_date="2022-01-01", price=14.99),
]
Book.objects.bulk_create(books)
# bulk_update — обновление нескольких объектов
books = list(Book.objects.all())
for book in books:
book.price += Decimal("1.0")
Book.objects.bulk_update(books, ['price'])
6. Django Shell
Django Shell — интерактивная Python-оболочка с настроенным Django-окружением.
# Запуск
python manage.py shell
# Импорт моделей
from store.models import Book, Publisher
# Использование ORM
all_books = Book.objects.all()
for book in all_books:
print(book)