✅ Решения — Урок 31
⚡ Быстрые ответы
- Задание 1: 1-D, 2-A, 3-B, 4-C
- Задание 2: A
- Задание 3: B (
django.db.models.functions) - Задание 4: A и C (
pageиpage_size) - Задание 5:
PageNumberPagination - Задание 6: C (
request.query_params.get('key'))
Блок 1: Решения — Extract*
Задание 1
Ответ: 1-D, 2-A, 3-B, 4-C
- ExtractMonth (1) → D. Извлекает месяц из даты
- ExtractDay (2) → A. Извлекает день из даты
- ExtractHour (3) → B. Извлекает час из времени
- ExtractQuarter (4) → C. Извлекает квартал из даты
Задание 2
Ответ: A — Book.objects.filter(published_date__month=1)
Встроенный lookup __month не требует явного импорта функций. Вариант B некорректен (нет суффикса). Вариант C создаёт аннотацию, но не фильтрует. Вариант D используется для получения одного объекта.
Задание 3
Ответ: B — from django.db.models.functions import ExtractYear
Все функции Extract* находятся в django.db.models.functions. В django.db.models — агрегации (Count, Sum). В rest_framework.filters — фильтры DRF.
Блок 2: Решения — Query Parameters
Задание 4
Ответ: A и C — page и page_size
В примере из лекции: GET /books/?page=2&page_size=3. Параметр page — номер страницы (из PageNumberPagination), page_size — размер страницы (переопределяется в get_page_size()). Параметры limit и offset используются в LimitOffsetPagination.
Задание 5
Ответ: PageNumberPagination
Из rest_framework.pagination. Используется через множественное наследование в APIView или через атрибут pagination_class в Generic Views.
Задание 6
Ответ: C — request.query_params.get('key')
В DRF request.query_params — предпочтительный способ доступа к GET-параметрам. request.GET (вариант A) тоже работает, но это Django-стиль. request.data (вариант D) — для тела POST/PUT-запроса.
Блок 3: Решения — Практические задачи
Задание 7
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
class BookByYearView(APIView):
def get(self, request):
year = request.query_params.get('year')
if year and year.isdigit():
books = Book.objects.filter(
published_date__year=int(year)
)
else:
books = Book.objects.all()
serializer = BookSerializer(books, many=True)
return Response(serializer.data)
# urls.py
urlpatterns = [
path('books/', BookByYearView.as_view(), name='book-by-year'),
]
Ключевые моменты:
- Проверяем, что
yearпередан (неNone) и является числом (.isdigit()) - При отсутствии параметра — возвращаем все книги (не пустой queryset)
- Преобразуем в
int(year)для корректной работы с lookup
Задание 8
Проблема: словарь filters всегда содержит оба ключа, даже если параметры не переданы. Тогда filter(author=None, published_date__year=None) вернёт пустой queryset вместо всех объектов.
Исправленный код:
class BookListView(APIView):
def get(self, request):
author = request.query_params.get('author')
year = request.query_params.get('year')
filters = {} # начинаем с пустого словаря
if author: # добавляем только если передан
filters['author'] = author
if year and year.isdigit(): # проверяем тип
filters['published_date__year'] = int(year)
books = Book.objects.filter(**filters)
return Response(BookSerializer(books, many=True).data)
Правило: никогда не добавляйте параметр в filters без проверки на None (и на корректность типа для числовых полей).