Пример 1: Базовая модель из лекции
Самая простая модель — основа всего. Точно как в лекции:
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200) # VARCHAR(200)
author = models.CharField(max_length=100) # VARCHAR(100)
published_date = models.DateField() # DATE
# Django автоматически добавит: id BIGINT PRIMARY KEY AUTOINCREMENT
SQL, который сгенерирует Django при migrate:
CREATE TABLE "myapp_book" (
"id" serial NOT NULL PRIMARY KEY,
"title" varchar(200) NOT NULL,
"author" varchar(100) NOT NULL,
"published_date" date NOT NULL
);
Пример 2: Все строковые поля
from django.db import models
class Article(models.Model):
# CharField — короткая строка, обязательно max_length
title = models.CharField(max_length=200, verbose_name='Заголовок')
# TextField — длинный текст, TEXT в БД
body = models.TextField(verbose_name='Текст статьи')
# EmailField — валидирует формат email
author_email = models.EmailField(verbose_name='Email автора')
# SlugField — URL-метка (только буквы, цифры, -_)
slug = models.SlugField(unique=True, verbose_name='Слаг')
# URLField — валидирует формат URL
source_url = models.URLField(blank=True, verbose_name='Источник')
Пример 3: Числовые поля
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
# IntegerField — целое число
quantity = models.IntegerField(default=0)
# PositiveIntegerField — только >= 0
views_count = models.PositiveIntegerField(default=0)
# DecimalField — денежные значения, фиксированная точность
# max_digits=10: всего 10 цифр; decimal_places=2: 2 после запятой
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
# FloatField — приближённое число (не для денег!)
rating = models.FloatField(default=0.0)
def __str__(self):
return f"{self.name} — {self.price} руб."
Пример 4: Поля дата/время с auto_now
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
# DateField — только дата
publish_date = models.DateField(null=True, blank=True)
# DateTimeField с auto_now_add — автоматически при создании объекта
# editable=False — нельзя менять в Admin
created_at = models.DateTimeField(auto_now_add=True)
# DateTimeField с auto_now — обновляется при каждом save()
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
auto_now vs auto_now_add:
auto_now_add=True— устанавливается один раз при создании объекта. Не меняется.auto_now=True— обновляется при каждом вызовеsave(). Подходит для «дата изменения».
editable=False автоматически).
Пример 5: Поле choices с TextChoices
from django.db import models
class Task(models.Model):
# TextChoices — современный способ задать choices (Django 3.0+)
class Status(models.TextChoices):
NEW = 'new', 'Новая'
IN_PROGRESS = 'in_progress', 'В работе'
PENDING = 'pending', 'Ожидание'
BLOCKED = 'blocked', 'Заблокирована'
DONE = 'done', 'Выполнена'
title = models.CharField(max_length=200)
status = models.CharField(
max_length=20,
choices=Status.choices,
default=Status.NEW,
verbose_name='Статус'
)
def __str__(self):
return f"{self.title} [{self.get_status_display()}]"
# get_FOO_display() — возвращает читаемое название статуса
Пример 6: ForeignKey — многие к одному
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200)
# ForeignKey — on_delete ОБЯЗАТЕЛЕН в Django 5.x
# CASCADE — при удалении автора все его книги тоже удаляются
author = models.ForeignKey(
Author,
on_delete=models.CASCADE,
related_name='books', # author.books.all() — все книги автора
verbose_name='Автор'
)
def __str__(self):
return f"{self.title} — {self.author.name}"
# Использование в shell:
# author = Author.objects.get(name="Пушкин")
# books = author.books.all() # через related_name
# book = Book.objects.get(id=1)
# print(book.author.name) # доступ к связанному объекту
Пример 7: ManyToManyField — многие ко многим
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=50, unique=True)
def __str__(self):
return self.name
class Article(models.Model):
title = models.CharField(max_length=200)
# ManyToManyField — Django сам создаёт промежуточную таблицу
tags = models.ManyToManyField(
Tag,
blank=True, # в форме можно не указывать теги
related_name='articles', # tag.articles.all()
verbose_name='Теги'
)
def __str__(self):
return self.title
# Использование в shell:
# article = Article.objects.get(id=1)
# article.tags.add(tag1, tag2) # добавить теги
# article.tags.all() # все теги статьи
# article.tags.remove(tag1) # убрать тег
Пример 8: OneToOneField — один к одному
from django.db import models
class User(models.Model):
username = models.CharField(max_length=150, unique=True)
email = models.EmailField(unique=True)
def __str__(self):
return self.username
class UserProfile(models.Model):
# OneToOneField — расширение модели User (доп. данные)
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name='profile', # user.profile — доступ к профилю
verbose_name='Пользователь'
)
bio = models.TextField(blank=True, verbose_name='О себе')
avatar = models.ImageField(
upload_to='avatars/',
null=True,
blank=True,
verbose_name='Аватар'
)
def __str__(self):
return f"Профиль: {self.user.username}"
# Использование в shell:
# user = User.objects.get(username='ivan')
# profile = user.profile # через related_name
# profile.bio = 'Python developer'
# profile.save()
Пример 9: Параметры полей — null, blank, default, validators
from django.db import models
from django.core.validators import MinLengthValidator, MinValueValidator
class Product(models.Model):
# null=True — разрешает NULL в БД (для строк лучше blank=True)
description = models.TextField(null=True, blank=True)
# blank=True — разрешает пустое значение в форме
subtitle = models.CharField(max_length=200, blank=True, default='')
# unique=True — значение должно быть уникальным
sku = models.CharField(max_length=50, unique=True)
# validators — проверка значения
price = models.DecimalField(
max_digits=10,
decimal_places=2,
validators=[MinValueValidator(0.01)], # цена > 0
verbose_name='Цена'
)
# help_text — подсказка в Admin
code = models.CharField(
max_length=10,
validators=[MinLengthValidator(3)],
help_text='Код продукта: 3–10 символов',
verbose_name='Код'
)
# error_messages — кастомные сообщения об ошибках
name = models.CharField(
max_length=200,
error_messages={
'blank': 'Название не может быть пустым.',
'unique': 'Продукт с таким названием уже существует.'
},
verbose_name='Название'
)
Пример 10: Регистрация в Admin
# myapp/admin.py
from django.contrib import admin
from .models import Book, Author
# Вариант 1: простая регистрация
admin.site.register(Book)
# Вариант 2: декоратор + кастомный AdminModel
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
list_display = ('name', 'email') # столбцы в списке объектов
search_fields = ('name', 'email') # поиск по этим полям
ordering = ('name',) # сортировка в списке