← Назад к вопросам

Расскажи про основные базовые классы, которые используешь в Django

2.0 Middle🔥 61 комментариев
#Django

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные классы Django

Django — мощный веб-фреймворк. Рассмотрю ключевые компоненты:

Models

ORM для работы с БД. Определяют структуру данных.

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

class User(AbstractUser):
    """Кастомная модель пользователя"""
    profile_picture = models.ImageField(upload_to='profiles/')
    bio = models.TextField(blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    
    class Meta:
        db_table = 'custom_users'
        verbose_name = 'User'
        verbose_name_plural = 'Users'
        indexes = [
            models.Index(fields=['email']),
        ]

class Post(models.Model):
    """Модель поста"""
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(
        User,
        on_delete=models.CASCADE,
        related_name='posts'
    )
    tags = models.ManyToManyField('Tag', related_name='posts')
    created_at = models.DateTimeField(auto_now_add=True)
    is_published = models.BooleanField(default=False)
    
    class Meta:
        ordering = ['-created_at']
    
    def __str__(self):
        return self.title

class Tag(models.Model):
    """Модель тега"""
    name = models.CharField(max_length=100, unique=True)
    slug = models.SlugField(unique=True)
    
    def __str__(self):
        return self.name

Views

Обработчики запросов. Есть два подхода: функциональные и классовые.

Функциональные представления

from django.shortcuts import render, get_object_or_404
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.views.decorators.csrf import csrf_exempt

@require_http_methods(["GET"])
def post_detail(request, post_id):
    post = get_object_or_404(Post, id=post_id)
    return render(request, 'posts/detail.html', {'post': post})

@require_http_methods(["POST"])
def create_post(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        content = request.POST.get('content')
        post = Post.objects.create(
            title=title,
            content=content,
            author=request.user
        )
        return JsonResponse({'id': post.id}, status=201)

Классовые представления (Class-Based Views)

from django.views import View
from django.views.generic import ListView, DetailView, CreateView, UpdateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy

class PostListView(ListView):
    """Список постов"""
    model = Post
    template_name = 'posts/list.html'
    context_object_name = 'posts'
    paginate_by = 20
    
    def get_queryset(self):
        return Post.objects.filter(is_published=True).select_related('author')

class PostDetailView(DetailView):
    """Детали поста"""
    model = Post
    template_name = 'posts/detail.html'
    context_object_name = 'post'
    slug_field = 'slug'
    slug_url_kwarg = 'slug'

class PostCreateView(LoginRequiredMixin, CreateView):
    """Создание поста"""
    model = Post
    fields = ['title', 'content', 'tags']
    template_name = 'posts/form.html'
    success_url = reverse_lazy('posts:list')
    
    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

class PostUpdateView(LoginRequiredMixin, UpdateView):
    """Обновление поста"""
    model = Post
    fields = ['title', 'content', 'tags']
    success_url = reverse_lazy('posts:list')
    
    def get_queryset(self):
        # Только автор может редактировать свой пост
        return Post.objects.filter(author=self.request.user)

class CustomView(View):
    """Кастомное представление"""
    def get(self, request):
        return render(request, 'template.html')
    
    def post(self, request):
        return JsonResponse({'status': 'ok'})

Serializers (DRF)

Для REST API используют Django REST Framework.

from rest_framework import serializers
from rest_framework.serializers import ModelSerializer

class UserSerializer(ModelSerializer):
    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'profile_picture']
        read_only_fields = ['id']

class PostSerializer(ModelSerializer):
    author = UserSerializer(read_only=True)
    tags = serializers.StringRelatedField(many=True)
    
    class Meta:
        model = Post
        fields = ['id', 'title', 'content', 'author', 'tags', 'created_at']
        read_only_fields = ['id', 'created_at']
    
    def validate_title(self, value):
        if len(value) < 3:
            raise serializers.ValidationError('Title too short')
        return value

ViewSets (DRF)

from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response

class PostViewSet(ModelViewSet):
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticatedOrReadOnly]
    
    def perform_create(self, serializer):
        serializer.save(author=self.request.user)
    
    @action(detail=True, methods=['post'])
    def publish(self, request, pk=None):
        post = self.get_object()
        post.is_published = True
        post.save()
        return Response({'status': 'published'})

Managers и QuerySets

Оптимизация запросов.

from django.db import models

class PublishedManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_published=True)

class Post(models.Model):
    # ... поля ...
    objects = models.Manager()  # default
    published = PublishedManager()  # кастомный
    
    @classmethod
    def get_trending(cls):
        return cls.published.annotate(
            like_count=models.Count('likes')
        ).order_by('-like_count')[:10]

# Использование
posts = Post.published.filter(author=user)  # только опубликованные
trending = Post.get_trending()  # трендовые посты

Формы

from django import forms
from django.forms import ModelForm

class PostForm(ModelForm):
    tags = forms.MultipleChoiceField(
        choices=[(t.id, t.name) for t in Tag.objects.all()],
        widget=forms.CheckboxSelectMultiple,
        required=False
    )
    
    class Meta:
        model = Post
        fields = ['title', 'content', 'tags']
        widgets = {
            'title': forms.TextInput(attrs={'class': 'form-control'}),
            'content': forms.Textarea(attrs={'class': 'form-control', 'rows': 5}),
        }
    
    def clean_title(self):
        title = self.cleaned_data['title']
        if Post.objects.filter(title=title).exists():
            raise forms.ValidationError('Title already exists')
        return title

Middleware

Обработчики для всех запросов.

class CustomMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # Before view
        request.custom_attr = 'value'
        
        response = self.get_response(request)
        
        # After view
        response['X-Custom-Header'] = 'value'
        return response

Signals

Обработка событий в моделях.

from django.db.models.signals import post_save, pre_delete
from django.dispatch import receiver

@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)

@receiver(pre_delete, sender=Post)
def delete_post_files(sender, instance, **kwargs):
    # Удалить файлы перед удалением поста
    instance.image.delete(save=False)

Тестирование

from django.test import TestCase, Client

class PostTests(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass123'
        )
    
    def test_create_post(self):
        post = Post.objects.create(
            title='Test',
            content='Content',
            author=self.user
        )
        self.assertEqual(post.author, self.user)
    
    def test_post_list_view(self):
        client = Client()
        response = client.get('/posts/')
        self.assertEqual(response.status_code, 200)

Django предоставляет полный стек для быстрой разработки веб-приложений с встроенными решениями для аутентификации, администрирования и ORM.