Перейти к содержанию

ЛР 3. Django REST & API

Отчет по лабораторной работе №3: Реализация серверной части на Django REST Framework

1. Цель работы

Разработать отказоустойчивую серверную часть (backend) для системы управления альпинистским клубом. Основные задачи включают: проектирование реляционной базы данных, создание гибкого API средствами Django REST Framework, реализацию системы разграничения прав доступа и автоматическое документирование всех интерфейсов.


2. Архитектура базы данных и моделирование

Проектирование велось с учетом необходимости хранения истории восхождений. Использовано 6 взаимосвязанных моделей. Особое внимание уделено реализации связи Many-to-Many между сущностями Alpinist и Climb.

Вместо стандартной связки использована промежуточная модель Participation (через аргумент through). Это архитектурное решение позволило хранить специфические данные для каждого участника в контексте конкретного похода: статус (успех, травма) и описание инцидентов. Таким образом, база данных поддерживает не только учет групп, но и детальную медицинскую и статистическую хронику.

Схема базы данных: Схема БД

Листинг ключевых моделей (models.py):

class Mountain(models.Model):
    name = models.CharField(max_length=100, verbose_name="Название горы")
    height = models.PositiveIntegerField(verbose_name="Высота")
    country = models.CharField(max_length=100)

class Climb(models.Model):
    route = models.ForeignKey(Route, on_delete=models.CASCADE, related_name="climbs")
    group_name = models.CharField(max_length=100)
    start_actual = models.DateTimeField(null=True, blank=True)
    is_group_success = models.BooleanField(default=False)
    participants = models.ManyToManyField(Alpinist, through='Participation')

class Participation(models.Model):
    alpinist = models.ForeignKey(Alpinist, on_delete=models.CASCADE)
    climb = models.ForeignKey(Climb, on_delete=models.CASCADE, related_name="details")
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='success')
    incident_details = models.TextField(blank=True)

Скриншот: Зарегистрированные модели в административной панели Django Админка БД


3. Сериализация данных и вложенные структуры

Для эффективной передачи данных по протоколу HTTP реализованы сериализаторы на базе ModelSerializer. Чтобы минимизировать количество запросов от клиента к серверу, применена технология Nested Serializers (вложенные сериализаторы).

Это позволяет при запросе данных о восхождении (Climb) сразу получать детальный список всех участников с их статусами, а также информацию о горе, на которую совершается подъем, через использование полей ReadOnlyField со ссылками на связанные объекты.

Листинг сериализатора (serializers.py):

class ClimbSerializer(serializers.ModelSerializer):
    mountain_name = serializers.ReadOnlyField(source='route.mountain.name')
    # отдаём список объектов Participation внутри объекта Climb
    details = ParticipationSerializer(many=True, read_only=True)

    class Meta:
        model = Climb
        fields = '__all__'


4. Бизнес-логика, агрегация и аналитические отчеты

Реализован набор эндпоинтов для решения задач администратора. Использованы возможности Django ORM для проведения сложных вычислений на стороне базы данных: * Фильтрация: Поиск участников и групп в заданных временных интервалах (__range). * Агрегация: Использование метода annotate и функции Count для подсчета количества альпинистов, покоривших каждую конкретную вершину. * Сложная группировка: Создан эндпоинт MountainReportView, который формирует иерархическую структуру данных: Гора -> Список групп -> Кол-во человек, а также вычисляет итоговое суммарное количество участников по всему отчету.

Листинг формирования сложного отчета (views.py):

class MountainReportView(APIView):
    def get(self, request):
        start_date = request.query_params.get('start')
        end_date = request.query_params.get('end')

        climbs = Climb.objects.filter(
            route__mountain=mtn, 
            start_actual__range=[start_date, end_date]
        ).annotate(members_count=Count('participants'))

Скриншот: Тестирование API и получение данных о горах Результат API


5. Безопасность и токенизация

Защита API реализована на базе библиотеки Djoser и стандартного механизма Token Authentication в Django REST Framework.

Механизм токенизации: 1. Выпуск токена: При успешном входе пользователя (POST запрос на /auth/token/login/) сервер генерирует уникальный алфавитно-цифровой ключ (Token), который сохраняется в базе данных и возвращается клиенту. 2. Хранение: Клиентское приложение сохраняет этот токен и прикрепляет его к каждому последующему запросу в HTTP-заголовке Authorization: Token <key>. 3. Валидация: Бэкенд перехватывает заголовок, сопоставляет токен с пользователем в базе и определяет его личность. 4. Права доступа: Использован класс IsAuthenticated, который блокирует доступ к критически важным эндпоинтам (например, просмотр списка гор или создание новых восхождений) для неавторизованных лиц.

Документирование: Все интерфейсы автоматически описаны с помощью Swagger (drf-spectacular). Это обеспечивает интерактивную среду, где можно протестировать запросы, увидеть требуемые параметры (Query Parameters) и форматы ответов без написания кода.

Скриншот: Перечень всех эндпоинтов системы в Swagger UI Swagger


6. Выводы

В результате выполнения работы была создана полноценная серверная архитектура, соответствующая принципам REST. Реализована сложная модель данных с промежуточными сущностями, настроена эффективная агрегация данных средствами ORM и обеспечена высокая безопасность системы за счет использования токенизации. Система готова к интеграции с клиентской частью. Все требования Варианта №15 выполнены.