🔖 Справочник команд и паттернов

⚡ Ключевые команды

# Создать приложение в модуле apps/
cd apps && python ../manage.py startapp tasks

# Миграции
python manage.py makemigrations
python manage.py migrate

# Git Agile workflow
git add .
git commit -m "feat: задание N — описание"
git push origin feature/task-N

Django-команды

Команда Описание
python manage.py startproject agile_projects Создать Django-проект
cd apps && python ../manage.py startapp tasks Создать приложение внутри папки apps/
python manage.py makemigrations Создать файлы миграций
python manage.py migrate Применить миграции
python manage.py runserver Запустить dev-сервер
python manage.py createsuperuser Создать администратора

Поля моделей

Поле Параметры в проекте
CharField max_length=20, validators=[MinLengthValidator(4)]
TextField Без ограничений длины, обязательно
DateTimeField auto_now_add=True | auto_now=True | null=True, blank=True
SmallIntegerField choices=Priority.choices(), default=Priority.MEDIUM[0]
ForeignKey on_delete=CASCADE | PROTECT, related_name='tasks'
ManyToManyField related_name='tasks' | related_name='project'
FileField upload_to='documents/'

DRF: паттерны APIView

# GET список
def get(self, request: Request) -> Response:
    qs = self.get_objects()
    if not qs.exists():
        return Response(data=[], status=status.HTTP_204_NO_CONTENT)
    serializer = MySerializer(qs, many=True)
    return Response(serializer.data, status=status.HTTP_200_OK)

# POST создание
def post(self, request: Request) -> Response:
    serializer = MySerializer(data=request.data)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return Response(serializer.validated_data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

# GET / PUT / DELETE деталь
def get_object(self, pk: int):
    return get_object_or_404(MyModel, pk=pk)

def put(self, request: Request, pk: int) -> Response:
    obj = self.get_object(pk)
    serializer = MySerializer(obj, data=request.data, partial=True)
    if serializer.is_valid(raise_exception=True):
        serializer.save()
        return Response(serializer.validated_data, status=status.HTTP_200_OK)

def delete(self, request: Request, pk: int) -> Response:
    self.get_object(pk).delete()
    return Response({"message": "Deleted successfully"}, status=status.HTTP_200_OK)

Регистрация URL

# agile_projects/urls.py
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/v1/', include('apps.routers')),
]

# apps/routers.py
urlpatterns = [
    path('tasks/', include('apps.tasks.urls')),
    path('projects/', include('apps.projects.urls')),
]

# apps/tasks/urls.py
urlpatterns = [
    path('tags/', TagListAPIView.as_view()),
    path('tags/<int:pk>/', TagDetailAPIView.as_view()),
]

# apps/projects/urls.py
urlpatterns = [
    path('', ProjectsListAPIView.as_view()),
    path('<int:pk>/', ProjectDetailAPIView.as_view()),
    path('files/', ProjectFileListAPIView.as_view()),
]

Утилиты работы с файлами

from pathlib import Path
import os

ALLOWED_EXTENSIONS = ['.csv', '.doc', '.pdf', '.xlsx', '.py']

def check_extension(filename: str) -> bool:
    return Path(filename).suffix in ALLOWED_EXTENSIONS

def check_file_size(file, required_size: int = 2) -> bool:
    return (file.size / (1024 * 1024)) <= required_size

def create_file_path(file_name: str) -> str:
    name, ext = file_name.split('.')
    return f"documents/{name}.{ext}"

def save_file(file_path: str, file_content) -> str:
    os.makedirs(os.path.dirname('documents/'), exist_ok=True)
    with open(file_path, 'wb') as f:
        for chunk in file_content.chunks():
            f.write(chunk)
    return file_path