🏠 Закрепляющая практика: Урок 27

Замечание: Для урока 27 (практикум) официального LMS-домашнего задания нет — оно совпадает с задачами урока. Данная страница содержит закрепляющее самостоятельное задание сверх практикума.

⚡ Кратко: что нужно сделать

Написать скрипт store_analysis.py в Django shell, который выводит аналитику по магазину: топ-5 категорий по выручке, топ-3 клиента по тратам, заказы за последние 7 дней, продукты с коротким сроком годности (менее 30 дней).

# Запуск
python manage.py shell
exec(open('store_analysis.py').read())

Задание

Напишите скрипт store_analysis.py, который при запуске через Django shell выводит аналитический отчёт по магазину. Используйте только изученные инструменты: aggregate(), annotate(), order_by(), timezone и срезы.

Что должен делать скрипт

  1. Топ-5 категорий по выручке
    Выручка = сумма (цена × количество) по всем продуктам в категории.
    Вывод: название категории и общая выручка, отсортированные по убыванию.
  2. Топ-3 клиента по сумме заказов
    Используйте OrderOrderItem → клиент.
    Вывод: имя, фамилия, общая сумма заказов.
  3. Заказы за последние 7 дней
    Используйте timezone.now() - timezone.timedelta(days=7).
    Вывод: ID заказа и дата.
  4. Продукты с коротким сроком годности (менее 30 дней)
    Вычислите разницу expiration_date - manufacturing_date через ExpressionWrapper.
    Отфильтруйте продукты с lifetime.days < 30.
    Вывод: название продукта и срок жизни в днях.

Подготовка окружения

# 1. Создать и активировать виртуальное окружение
python -m venv venv
# Windows PowerShell:
.\venv\Scripts\Activate.ps1

# 2. Установить зависимости
pip install django

# 3. Убедиться, что проект настроен
python manage.py check

# 4. Загрузить тестовые данные (если ещё не загружены)
python manage.py shell
from store_data import *
export_data()
exit()

Решение

store_analysis.py

# store_analysis.py — аналитика по магазину (запускать через Django shell)
from django.db.models import Sum, F, Count, Avg, ExpressionWrapper, fields
from django.utils import timezone
from store.models import Product, Order, OrderItem, ProductDetail

print("=" * 50)
print("АНАЛИТИКА МАГАЗИНА")
print("=" * 50)

# 1. Топ-5 категорий по выручке
print("\n1. Топ-5 категорий по выручке:")
top_categories = Product.objects.values('category__name').annotate(
    revenue=Sum(F('price') * F('quantity'))
).order_by('-revenue')[:5]

for i, cat in enumerate(top_categories, 1):
    print(f"  {i}. {cat['category__name']}: {cat['revenue']}")

# 2. Топ-3 клиента по сумме заказов
print("\n2. Топ-3 клиента по сумме заказов:")
top_customers = Order.objects.values(
    'customer__first_name',
    'customer__last_name'
).annotate(
    total_spent=Sum(F('order_items__price') * F('order_items__quantity'))
).order_by('-total_spent')[:3]

for i, cust in enumerate(top_customers, 1):
    print(
        f"  {i}. {cust['customer__first_name']} {cust['customer__last_name']}: "
        f"{cust['total_spent']}"
    )

# 3. Заказы за последние 7 дней
print("\n3. Заказы за последние 7 дней:")
week_ago = timezone.now() - timezone.timedelta(days=7)
recent_orders = Order.objects.filter(order_date__gte=week_ago)

if recent_orders.exists():
    for order in recent_orders:
        print(f"  Заказ #{order.id}, дата: {order.order_date.date()}")
else:
    print("  Нет заказов за последние 7 дней")

# 4. Продукты с коротким сроком годности (менее 30 дней)
print("\n4. Продукты с коротким сроком годности:")
short_lifetime = ProductDetail.objects.annotate(
    lifetime=ExpressionWrapper(
        F('expiration_date') - F('manufacturing_date'),
        output_field=fields.DurationField()
    )
).filter(lifetime__lt=timezone.timedelta(days=30)).select_related('product')

if short_lifetime.exists():
    for detail in short_lifetime:
        print(f"  {detail.product.name}: {detail.lifetime.days} дней")
else:
    print("  Нет продуктов с коротким сроком годности")

print("\n" + "=" * 50)

Как запустить скрипт

# Вариант 1: через shell
python manage.py shell
exec(open('store_analysis.py').read())

# Вариант 2: передать как скрипт напрямую
python manage.py shell < store_analysis.py

Проверка в VS Code

Настройка терминала

  1. Открыть встроенный терминал: Ctrl + `
  2. Активировать venv: .\venv\Scripts\Activate.ps1
  3. Запустить: python manage.py shell
  4. Выполнить: exec(open('store_analysis.py').read())

Настройка launch.json для отладки (F5)

// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Django Shell",
      "type": "debugpy",
      "request": "launch",
      "program": "${workspaceFolder}/manage.py",
      "args": ["shell"],
      "django": true,
      "justMyCode": true
    }
  ]
}

Точки останова

  1. Откройте store_analysis.py в VS Code
  2. Кликните левее номера строки, чтобы поставить точку останова (красная точка)
  3. Нажмите F5 для запуска в режиме отладки
  4. В панели Variables проверьте содержимое QuerySet

Критерии выполнения

  • Скрипт запускается без ошибок
  • Все 4 блока вывода присутствуют
  • Использован timezone.now(), а не datetime.now()
  • ExpressionWrapper содержит output_field=fields.DurationField()
  • Срезы применены на уровне QuerySet ([:5], [:3]), а не после list()

Связь с материалами урока

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