💻 Примеры: Django-блок в действии

🎯 Ключевые паттерны блока К оглавлению урока

⚡ Минимальный пример

# models.py
class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.ForeignKey('Author', on_delete=models.CASCADE)
    published_date = models.DateField()

    def __str__(self):
        return f"{self.title} by {self.author}"

    class Meta:
        ordering = ['-published_date']

# admin.py
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'published_date')
    search_fields = ('title', 'author__name')
    list_filter = ('published_date',)

# ORM
books = Book.objects.filter(published_date__gt="2000-01-01").order_by('-published_date')
Book.objects.filter(author__name="Orwell").update(price=9.99)

Пример 1: Полная модель с __str__ и Meta

from django.db import models

class Publisher(models.Model):
    name = models.CharField(max_length=100)
    established_date = models.DateField()

    def __str__(self):
        return self.name

    class Meta:
        ordering = ['name']
        verbose_name = 'Publisher'
        verbose_name_plural = 'Publishers'


class Book(models.Model):
    title = models.CharField(max_length=200)
    author = models.CharField(max_length=100)
    published_date = models.DateField()
    price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    discounted_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
    is_bestseller = models.BooleanField(default=False)
    created_at = models.DateTimeField(null=True, blank=True)
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE, null=True, blank=True)

    def __str__(self):
        return f"{self.title} by {self.author}"

    class Meta:
        db_table = 'library_book'
        ordering = ['-published_date']
        verbose_name = 'Book'
        verbose_name_plural = 'Books'
        unique_together = ('title', 'author')
        indexes = [
            models.Index(fields=['title', 'author']),
            models.Index(fields=['published_date'], name='published_idx'),
        ]

Пример 2: ModelAdmin с инлайнами и action

from django.contrib import admin
from django.utils import timezone
from .models import Book, Publisher


class BookInline(admin.TabularInline):
    model = Book
    extra = 1
    fields = ('title', 'author', 'published_date', 'price')


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(Publisher)
class PublisherAdmin(admin.ModelAdmin):
    list_display = ('name', 'established_date')
    search_fields = ('name',)
    inlines = [BookInline]


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('title', 'author', 'publisher', 'published_date', 'is_bestseller', 'created_at')
    search_fields = ('title', 'author')
    list_filter = ('is_bestseller', 'published_date', 'publisher')
    ordering = ('-published_date',)
    list_per_page = 25
    actions = [update_created_at]

Пример 3: Кастомная модель User

from django.db import models
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 _


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'

Пример 4: Регистрация кастомного User в admin

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.utils.translation import gettext_lazy as _
from .models import CustomUser


class CustomUserAdmin(BaseUserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name', 'email', 'birth_date')}),
        (_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('username', 'password1', 'password2'),
        }),
    )
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
    search_fields = ('username', 'first_name', 'last_name', 'email')
    ordering = ('username',)

admin.site.register(CustomUser, CustomUserAdmin)

Пример 5: CRUD через ORM (Django Shell)

from store.models import Book, Publisher
from django.db.models import Q, F
from decimal import Decimal

# --- Создание ---
publisher = Publisher.objects.create(name="Penguin Books", established_date="2023-01-01")
book = Book.objects.create(
    title="The Great Gatsby",
    author="F. Scott Fitzgerald",
    published_date="1925-04-10",
    price=15.00,
    publisher=publisher
)

# --- Чтение ---
all_books = Book.objects.all()
first = Book.objects.first()
count = Book.objects.count()

# Фильтрация с lookups
modern = Book.objects.filter(published_date__gt="2000-01-01")
classics = Book.objects.filter(title__icontains="great")
cheap = Book.objects.filter(price__lt=20, is_bestseller=True)

# Метод get
try:
    book = Book.objects.get(title="The Great Gatsby")
except Book.DoesNotExist:
    print("Не найдено")

# Q-объекты
result = Book.objects.filter(
    Q(is_bestseller=True) | Q(published_date__gt="2000-01-01")
)

# --- Обновление ---
book.title = "Updated Title"
book.save()

# Массовое обновление
Book.objects.filter(author="F. Scott Fitzgerald").update(price=9.99)

# F-выражения
Book.objects.update(price=F('price') * 1.10)
Book.objects.update(discounted_price=F('price') * 0.9)

# --- Удаление ---
book = Book.objects.get(id=1)
book.delete()
Book.objects.filter(author="Old Author").delete()

# --- Bulk-операции ---
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)

books_qs = list(Book.objects.all())
for b in books_qs:
    b.price += Decimal("1.0")
Book.objects.bulk_update(books_qs, ['price'])

Пример 6: ForeignKey на встроенный User

from django.db import models
from django.contrib.auth.models import User


class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.title