💻 Примеры: ORM-запросы и DRF views
⚡ Ключевые примеры
# annotate + ExtractWeekDay
from django.db.models.functions import ExtractWeekDay
files = ProjectFile.objects.annotate(weekday=ExtractWeekDay('created_at')).filter(weekday=2)
# annotate + Count + order_by
from django.db.models import Count
User.objects.annotate(cnt=Count('tasks__id')).order_by('-cnt').values_list('username','cnt')
# Paginator
from django.core.paginator import Paginator
p = Paginator(Task.objects.all(), 10)
for task in p.get_page(1):
print(task.name)
# DRF сериализатор + view
class AllProjectsSerializer(ModelSerializer):
class Meta:
model = Project
fields = ['id', 'name']
@api_view(['GET'])
def get_all_projects(request):
qs = Project.objects.all()
if not qs.exists():
return JsonResponse([], status=204, safe=False)
return JsonResponse(AllProjectsSerializer(qs, many=True).data, status=200, safe=False)
Пример 1: Фильтрация проектов по текущему месяцу
from django.utils import timezone
from management_app.models.project import Project
# Получить проекты, созданные в текущем месяце
cur_month_projects = Project.objects.filter(
date_of_creation__month=timezone.now().month
)
if cur_month_projects:
for proj in cur_month_projects:
print("=" * 50)
print(proj.name)
print(proj.date_of_creation)
else:
print("EMPTY DATA")
timezone.now().month — целое число (1–12). Django подставляет его в SQL WHERE EXTRACT(MONTH FROM date_of_creation) = ...
Пример 2: ExtractWeekDay — файлы, загруженные в понедельник
from django.db.models.functions import ExtractWeekDay
from management_app.models.project import ProjectFile
monday_files = ProjectFile.objects.annotate(
weekday=ExtractWeekDay('created_at')
).filter(
weekday=2 # 2 = понедельник в ISO-стиле Django
)
if monday_files:
for f in monday_files:
print(f.file_name, f.file_path)
else:
print("EMPTY DATA")
ExtractWeekDay: 1 = воскресенье, 2 = понедельник, 3 = вторник, ... 7 = суббота. Это поведение базы данных (СУБД), а не Python (где 0 = понедельник).
Пример 3: annotate + Avg + вывод результата
from django.db.models import Avg
from management_app.models import Project
# Среднее количество задач на каждом проекте
projects_with_avg = Project.objects.annotate(avg_tasks=Avg('tasks__id'))
for project in projects_with_avg:
print(f"Project: {project.name}, Avg tasks: {project.avg_tasks}")
Avg('tasks__id') считает среднее ID связанных задач, что де-факто равно количеству (при автоинкрементном id). Для точного подсчёта лучше использовать Count('tasks').
Пример 4: annotate + values_list + order_by
from django.db.models import Count
from django.contrib.auth.models import User
# Пользователи, отсортированные по убыванию количества задач
sorted_users = User.objects.annotate(
count_of_tasks=Count('tasks__id')
).order_by('-count_of_tasks').values_list('username', 'count_of_tasks')
print(sorted_users.query) # вывести SQL-запрос для отладки
for username, count in sorted_users:
print(f"{username} | {count}")
Пример 5: Paginator — разбивка задач на страницы
from management_app.models import Task
from django.core.paginator import Paginator
tasks = Task.objects.all()
paginator = Paginator(tasks, 10) # 10 задач на страницу
page_number = 1
page = paginator.get_page(page_number)
print(f"Страница {page.number} из {paginator.num_pages}")
for task in page:
print("=" * 50)
print(task.name)
print(task.status)
print(task.priority)
print(task.assignee.username)
Пример 6: Полный сериализатор + view (DRF)
# management_app/serializers/projects.py
from rest_framework.serializers import ModelSerializer
from management_app.models import Project
class AllProjectsSerializer(ModelSerializer):
class Meta:
model = Project
fields = ['id', 'name']
# management_app/views.py (или views/projects.py)
from rest_framework.request import Request
from rest_framework.decorators import api_view
from rest_framework import status
from django.http import JsonResponse
from management_app.serializers.projects import AllProjectsSerializer
from management_app.models.project import Project
@api_view(['GET'])
def get_all_projects(request: Request) -> JsonResponse:
all_projects = Project.objects.all()
if not all_projects.exists():
return JsonResponse(
[],
status=status.HTTP_204_NO_CONTENT,
safe=False
)
serialized_data = AllProjectsSerializer(all_projects, many=True)
return JsonResponse(
serialized_data.data,
status=status.HTTP_200_OK,
safe=False
)
Пример 7: Вложенный сериализатор — TaskInfoSerializer
# management_app/serializers/tasks.py
from rest_framework import serializers
from management_app.models import Task
from management_app.serializers.tags import TagsSerializer
class TaskInfoSerializer(serializers.ModelSerializer):
tags = TagsSerializer(many=True) # теги — вложенный объект
class Meta:
model = Task
fields = [
'id', 'name', 'status', 'priority',
'tags', 'project', 'created_date', 'due_date'
]
# Использование в view
@api_view(['GET'])
def get_task_by_id(request: Request, task_id: int) -> JsonResponse:
try:
task = Task.objects.get(id=task_id)
except Task.DoesNotExist:
return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
data = TaskInfoSerializer(task)
return JsonResponse(data.data, status=status.HTTP_200_OK)
Пример 8: CRUD для тегов — полный набор endpoints
# management_app/serializers/tags.py
from rest_framework import serializers
from management_app.models import Tag
class TagsSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'
# management_app/views.py — полный CRUD для Tag
@api_view(['GET'])
def get_tag_by_id(request: Request, tag_id: int) -> JsonResponse:
try:
tag = Tag.objects.get(id=tag_id)
except Tag.DoesNotExist:
return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
return JsonResponse(TagsSerializer(tag).data, status=status.HTTP_200_OK)
@api_view(['PUT'])
def update_required_tag(request: Request, tag_id: int) -> JsonResponse:
try:
tag = Tag.objects.get(id=tag_id)
except Tag.DoesNotExist:
return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
serializer = TagsSerializer(tag, request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return JsonResponse(serializer.data, status=status.HTTP_200_OK)
@api_view(['POST'])
def create_new_tag(request: Request) -> JsonResponse:
new_tag = TagsSerializer(data=request.data)
if new_tag.is_valid(raise_exception=True):
new_tag.save()
return JsonResponse(new_tag.data, status=status.HTTP_201_CREATED)
return JsonResponse(new_tag.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['DELETE'])
def delete_required_tag(request: Request, tag_id: int) -> JsonResponse:
try:
tag = Tag.objects.get(id=tag_id)
except Tag.DoesNotExist:
return JsonResponse({}, status=status.HTTP_204_NO_CONTENT)
tag.delete()
return JsonResponse({'message': 'Tag deleted successfully'}, status=status.HTTP_200_OK)