⚡ Ключевые команды
# Создать приложение в модуле 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