📝 Задания мини-проекта Agile Projects ч.2

6 задач: CRUD проектов (1) · задачи + пагинация (2) · CRUD задач (3) · файлы (4–5) · кастомный User (6)

⚡ Все задачи — кратко

  1. Задание 1: ProjectDetailSerializer (name, description, count_of_files), ProjectDetailAPIView (GET/PUT partial=True/DELETE), URL /api/v1/projects/<pk>/, коммит
  2. Задание 2: AllTasksSerializer (SlugRelatedField: project.name, assignee.email), CreateTaskSerializer с валидаторами (name ≥ 10, description ≥ 50, priority choices, project по имени, tags, deadline), TasksListAPIView (пагинация 5, фильтр по project_name/assignee_email), POST, URL /api/v1/tasks/, коммит
  3. Задание 3: TaskDetailSerializer (вложенный ProjectShortInfoSerializer, исключить updated_at/deleted_at), CreateUpdateTaskSerializer.update(), TaskDetailAPIView (GET/PUT partial/DELETE), URL /api/v1/tasks/<pk>/, коммит
  4. Задание 4: utils/upload_file_helpers.py (4 функции), AllProjectFilesSerializer, CreateProjectFileSerializer (валидация ASCII + расширения, create с chunked save), ProjectFileListGenericView (GET + POST), URL /api/v1/projects/files/, коммит
  5. Задание 5: ProjectFileDetailSerializer (вложенный ProjectShortInfoSerializer), ProjectFileDetailGenericView (GET/DELETE + физическое удаление файла), URL /api/v1/projects/files/<pk>/, коммит
  6. Задание 6: python manage.py startapp users, модель User (AbstractBaseUser, 13 полей, USERNAME_FIELD=email), AUTH_USER_MODEL в settings.py, пересоздать БД, миграции, createsuperuser
Контекст: Продолжаешь разработку REST API-платформы «Agile Projects» (начата в уроке 28). К этому моменту реализованы модели Tag, Project, ProjectFile, Task и базовый CRUD тегов. Теперь реализуем CRUD для проектов, API задач с пагинацией, загрузку файлов и кастомного пользователя.

Задание 1 — Получение, обновление и удаление проекта

  1. Создайте новый сериализатор ProjectDetailSerializer для получения конкретной информации по проекту:
    • name
    • description
    • created_at
    • count_of_files
  2. Напишите новый класс-отображение ProjectDetailAPIView для получения конкретного проекта, обновления и удаления проекта.
  3. При обновлении полученного проекта добавьте возможность частичного обновления полей.
  4. Зарегистрируйте новый эндпоинт, проверьте как отрабатывают запросы GET, PUT, DELETE.
  5. Зафиксируйте все изменения, сделайте запрос на слияние.
Файлы для изменений: apps/projects/serializers/project_serializers.py, apps/projects/views/project_views.py, apps/projects/urls.py

Задание 2 — Задачи для проекта, сотрудник с пагинацией, создание задачи

  1. В приложении tasks, в модуле serializers создайте новый файл tasks_serializers.py.
  2. Реализуйте сериализатор AllTasksSerializer для отображения краткой информации о задачах. Поля для отображения:
    • name
    • status
    • priority
    • project (название проекта)
    • assignee (email сотрудника)
    • deadline
  3. Реализуйте сериализатор CreateTaskSerializer для создания новой задачи. Поля для создания новой задачи:
    • name
    • description
    • priority
    • project (заполняется не по id, а по имени проекта)
    • tags
    • deadline
  4. Добавьте в сериализатор на создание новой задачи валидаторы полей:
    • name (минимальная длина)
    • description (минимальная длина)
    • priority (передаётся строго число, переданное число должно быть в доступных choices, от 1 до 5)
    • project (передаётся имя проекта, поиск среди всех проектов. Если такого имени нет — выводить сообщение об ошибке, что проекта не существует)
    • tags (список имён тегов, поиск среди всех тегов. Если тега по имени найдено не было — выводить сообщение об ошибке)
    • deadline (не может быть в прошлом)
  5. Переопределите метод create для добавления информации тегов в промежуточную таблицу.
  6. Напишите класс-отображение AllTasksListAPIView для получения списка всех задач, привязанных к конкретному проекту, или сотруднику на выбор. Реализуйте пагинацию для отображения только первых пяти записей на одной странице. Добавьте метод post для создания задачи.
  7. Зарегистрируйте новый эндпоинт, проверьте как отрабатывают запросы GET, POST.
  8. Зафиксируйте все изменения, сделайте запрос на слияние.
Файлы для изменений: apps/tasks/serializers/task_serializers.py, apps/tasks/views/task_views.py, apps/tasks/urls.py

Задание 3 — Получение, обновление и удаление задачи

  1. Напишите новый сериализатор TaskDetailSerializer:
    • Сериализатор должен принимать все поля, кроме updated_at, deleted_at
    • Более подробное отображение информации о проекте (вложенный сериализатор ProjectShortInfoSerializer)
  2. В уже написанном сериализаторе CreateTaskSerializer поменяйте название на CreateUpdateTaskSerializer, добавьте метод update на обновление существующей задачи.
  3. Создайте классовое отображение TaskDetailAPIView для получения полной информации о конкретной задаче по её ID, возможности полного, или частичного обновления задачи и удаления задачи.
  4. Зарегистрируйте новый эндпоинт, проверьте как отрабатывают запросы GET, PUT, DELETE.
  5. Зафиксируйте все изменения, сделайте запрос на слияние.
Файлы для изменений: apps/tasks/serializers/task_serializers.py, apps/projects/serializers/project_serializers.py, apps/tasks/views/task_views.py, apps/tasks/urls.py

Задание 4 — Работа с файлами (загрузка)

  1. В приложении projects создайте новый модуль utils.
  2. Создайте в этом модуле файл upload_file_helpers.py.
  3. В этом файле необходимо создать функции:
    • Функция на проверку валидных расширений файла
    • Функция на проверку размерности файла (файл не должен быть больше 2 MB)
    • Функция на создание пути для сохранения файла
    • Функция на сохранение файла (файл должен записываться по частям для избежания потенциальных ошибок и потери данных)
  4. В модуле serializers в приложении projects создайте новый файл project_file_serializers.py.
  5. Создайте сериализатор AllProjectFilesSerializer для отображения краткой информации по всем файлам:
    • id
    • file_name
    • project
  6. Создайте сериализатор CreateProjectFileSerializer для создания нового файла:
    • Для создания необходимо только поле file_name
    • Поле file_name необходимо валидировать:
      • Проверка на наличие символов из таблицы ASCII
      • Проверка на доступные расширения файлов (pdf, csv, doc, xlsx)
  7. Переопределите метод create:
    • Перед сохранением файла необходимо создать путь для сохранения
    • Необходимо получить из тела запроса сам файл и проверить его на размерность (не более 2 MB)
    • Если файл проходит все проверки — сохранить его в проекте, сохранить объект файла
    • Если файл слишком большой — поднять исключение валидации с сообщением об ошибке
  8. Напишите класс-отображение ProjectFileListGenericView для получения списка всех файлов:
    • Реализовать метод на получение всех файлов для конкретного проекта по имени проекта. Если имя проекта не было передано — выводить список полностью всех файлов
  9. Добавьте в класс-отображение ProjectFileListGenericView метод post для создания нового файла и привязки его к конкретному проекту (проект получать через поле id, которое будет передаваться в теле запроса).
  10. Зарегистрируйте новый эндпоинт, проверьте как отрабатывают запросы GET, POST.
  11. Зафиксируйте все изменения, сделайте запрос на слияние.
Файлы для создания: apps/projects/utils/__init__.py, apps/projects/utils/upload_file_helpers.py, apps/projects/serializers/project_file_serializers.py, apps/projects/views/project_file_views.py

Задание 5 — Получение файла, возможность его удаления

  1. Создайте сериализатор ProjectFileDetailSerializer для получения подробной информации о файле:
    • name
    • created_at
    • project (вложенный сериализатор для отображения названия проекта)
  2. Напишите классовое отображение ProjectFileDetailGenericView для получения информации о конкретном файле и проекте, к которому он привязан, а также возможности удаления этого файла, как из базы данных, так и из проекта (физическое удаление).
  3. Зарегистрируйте новый эндпоинт, проверьте как отрабатывают запросы GET, DELETE.
  4. Зафиксируйте все изменения, сделайте запрос на слияние.
Файлы для изменений: apps/projects/serializers/project_file_serializers.py, apps/projects/views/project_file_views.py, apps/projects/utils/upload_file_helpers.py, apps/projects/urls.py

Задание 6 — Создание кастомного пользователя

  1. Удалите существующую базу.
  2. Создайте новое приложение users, зарегистрируйте его в проекте.
  3. Создайте свою собственную модель User, в которой будут поля:
    • username — строковое поле, не более 50 символов, уникальное, обязательно к заполнению
    • first_name — строковое поле, не более 40 символов, обязательно к заполнению
    • last_name — строковое поле, не более 40 символов, обязательно к заполнению
    • email — поле email, уникальное, обязательное к заполнению
    • phone — строковое поле, не более 75 символов, не обязательно к заполнению
    • is_staff — административное логическое поле, по умолчанию False
    • is_active — логическое поле, по умолчанию True
    • date_joined — поле даты и времени, заполняется автоматически при создании
    • last_login — поле даты и времени, заполняется при входе в систему
    • updated_at — поле даты и времени, заполняется автоматически при всех обновлениях
    • deleted_at — поле даты и времени, заполняется только если поле deleted переходит в состояние True
    • deleted — логическое поле, по умолчанию False
    • project — связь с моделью Project. При удалении проекта все сотрудники также удаляются, связующее поле у проекта — users, при создании пользователя проекта у него может и не быть
    • position — строковое поле выбора из готовых вариантов: Ceo, Cto, Designer, Programmer, Product_owner, Project_owner, Project_manager, Qa
  4. Укажите поле email, как поле для входа в систему.
  5. Добавьте дополнительные поля для регистрации: username, last_name, first_name.
  6. Перепишите настройки django на работу с пользователем в файле settings.py.
  7. Переопределите связь с новым пользователем в других моделях, где была связь с пользователем (модель Task).
  8. Проведите миграции и убедитесь, что всё работает.
Файлы для создания/изменений: python manage.py startapp users, apps/users/models.py, apps/users/choices/positions.py, settings.py (AUTH_USER_MODEL), apps/tasks/models/task_model.py (поменять ForeignKey на settings.AUTH_USER_MODEL)
Посмотреть решения →