🔖 Справочник: ORM и DRF — шпаргалка

⚡ Ключевые команды и паттерны

# ORM — дата и время
Project.objects.filter(date_of_creation__month=timezone.now().month)
ProjectFile.objects.annotate(weekday=ExtractWeekDay('created_at')).filter(weekday=2)

# ORM — агрегация
Project.objects.all().count()
Project.objects.annotate(avg_tasks=Avg('tasks__id'))
User.objects.annotate(cnt=Count('tasks__id')).values_list('username', 'cnt')

# ORM — сортировка
Task.objects.order_by('priority', 'due_date')
User.objects.annotate(cnt=Count('tasks__id')).order_by('-cnt')

# Пагинация
paginator = Paginator(Task.objects.all(), 10)
page = paginator.get_page(1)

# DRF — сериализатор
class MySerializer(ModelSerializer):
    class Meta:
        model = MyModel
        fields = ['id', 'name']

# DRF — view
@api_view(['GET'])
def my_view(request):
    qs = MyModel.objects.all()
    data = MySerializer(qs, many=True)
    return JsonResponse(data.data, status=status.HTTP_200_OK, safe=False)

← К оглавлению урока

ORM — работа с датой

Метод / lookupОписаниеПример
__monthФильтр по месяцуfilter(date__month=6)
__yearФильтр по годуfilter(date__year=2025)
__dayФильтр по днюfilter(date__day=15)
timezone.now()Текущая дата/времяfilter(date__month=timezone.now().month)
ExtractWeekDayДень недели (1=вс, 2=пн, ...)annotate(wd=ExtractWeekDay('created_at'))

ORM — агрегация и аннотации

МетодОписаниеВозвращает
.count()Количество объектовint
.aggregate(x=Count(...))Итоговое значение по всему QSdict: {'x': N}
.annotate(x=Count(...))Значение для каждого объектаQuerySet с доп. полем x
Count('field')Количество связанных объектовчисло
Avg('field')Среднее значениеfloat или None
.values_list('f1','f2')Выборка конкретных полейQuerySet кортежей

ORM — сортировка и пагинация

# Сортировка по нескольким полям
Task.objects.order_by('priority', 'due_date')
# Обратный порядок
User.objects.annotate(cnt=Count('tasks__id')).order_by('-cnt')

# Пагинация
from django.core.paginator import Paginator

paginator = Paginator(queryset, per_page)
page_obj = paginator.get_page(page_number)  # безопасно
# page_obj.has_next(), page_obj.has_previous(), paginator.num_pages

DRF — установка и настройка

pip install djangorestframework

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
]

# requirements.txt
djangorestframework

DRF — сериализаторы

ПаттернОписание
ModelSerializerБазовый класс для сериализаторов на основе модели
Meta.fields = [...]Список полей для сериализации
Meta.fields = '__all__'Все поля модели
Serializer(obj)Один объект
Serializer(qs, many=True)QuerySet / список объектов
Serializer(data=request.data)Десериализация (POST/PUT)
.is_valid(raise_exception=True)Валидация входных данных
.save()Создание или обновление объекта
.dataСериализованные данные (dict или list)

Вложенный сериализатор

class TaskInfoSerializer(serializers.ModelSerializer):
    tags = TagsSerializer(many=True)   # вложенный

    class Meta:
        model = Task
        fields = ['id', 'name', 'tags', ...]

DRF — функциональные views

from rest_framework.request import Request
from rest_framework.decorators import api_view
from rest_framework import status
from django.http import JsonResponse

# GET — список
@api_view(['GET'])
def get_all_items(request: Request) -> JsonResponse:
    qs = MyModel.objects.all()
    if not qs.exists():
        return JsonResponse([], status=status.HTTP_204_NO_CONTENT, safe=False)
    data = MySerializer(qs, many=True)
    return JsonResponse(data.data, status=status.HTTP_200_OK, safe=False)

# GET — один объект по id
@api_view(['GET'])
def get_item_by_id(request: Request, item_id: int) -> JsonResponse:
    try:
        obj = MyModel.objects.get(id=item_id)
    except MyModel.DoesNotExist:
        return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
    data = MySerializer(obj)
    return JsonResponse(data.data, status=status.HTTP_200_OK)

# POST — создание
@api_view(['POST'])
def create_item(request: Request) -> JsonResponse:
    serializer = MySerializer(data=request.data)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return JsonResponse(serializer.data, status=status.HTTP_201_CREATED)
    return JsonResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

# PUT — обновление
@api_view(['PUT'])
def update_item(request: Request, item_id: int) -> JsonResponse:
    try:
        obj = MyModel.objects.get(id=item_id)
    except MyModel.DoesNotExist:
        return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
    serializer = MySerializer(obj, request.data)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return JsonResponse(serializer.data, status=status.HTTP_200_OK)

# DELETE — удаление
@api_view(['DELETE'])
def delete_item(request: Request, item_id: int) -> JsonResponse:
    try:
        obj = MyModel.objects.get(id=item_id)
    except MyModel.DoesNotExist:
        return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
    obj.delete()
    return JsonResponse({'message': 'Deleted successfully'}, status=status.HTTP_200_OK)

DRF — регистрация URL

# management_app/urls.py
from django.urls import path
from management_app.views import (
    get_all_projects, get_all_tasks, get_all_tags,
    get_tag_by_id, create_new_tag, update_required_tag,
    delete_required_tag, get_task_by_id
)

urlpatterns = [
    path('projects/', get_all_projects),
    path('tasks/', get_all_tasks),
    path('tasks/<int:task_id>/', get_task_by_id),
    path('tags/', get_all_tags),
    path('tags/create/', create_new_tag),         # ВАЖНО: до <int:tag_id>
    path('tags/<int:tag_id>/', get_tag_by_id),
    path('tags/<int:tag_id>/update/', update_required_tag),
    path('tags/<int:tag_id>/delete/', delete_required_tag),
]

# project_management/urls.py
from django.urls import path, include
urlpatterns = [
    path('management_app/', include('management_app.urls')),
]
Маршрут tags/create/ должен стоять перед tags/<int:tag_id>/, иначе Django попытается преобразовать строку "create" в int и выдаст 404.

← К оглавлению урока