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

⚡ Шпаргалка

# Django-команды
python manage.py startapp users
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser

# settings.py
AUTH_USER_MODEL = 'users.User'

# AbstractBaseUser минимум
class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username"]
    objects = UserManager()

# FileResponse
from django.http import FileResponse
response = FileResponse(file_handle, content_type='application/octet-stream')
response['Content-Disposition'] = f'attachment; filename="{name}"'

# SlugRelatedField
assignee = serializers.SlugRelatedField(slug_field='email', queryset=User.objects.all(), required=False)

Django-команды проекта

Команда Что делает
python manage.py startapp usersСоздать новое приложение users
python manage.py makemigrationsСгенерировать файлы миграций
python manage.py migrateПрименить миграции
python manage.py createsuperuserСоздать суперпользователя
python manage.py runserverЗапустить dev-сервер

Git-команды (Agile workflow)

# Стандартный цикл задачи
git checkout -b feature/task-35-N
git add apps/...
git commit -m "feat: описание задачи 35-N"
git push origin feature/task-35-N
# Создать Pull Request в GitHub/GitLab

AbstractBaseUser — шаблон

from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin, UserManager
from django.db import models

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(unique=True)
    username = models.CharField(max_length=50, unique=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["username", "first_name", "last_name"]
    objects = UserManager()

    class Meta:
        verbose_name = "User"

FileResponse — скачивание

from django.http import FileResponse
from rest_framework.generics import get_object_or_404
from rest_framework.views import APIView
from rest_framework.request import Request

class DownloadProjectFileView(APIView):
    def get_object(self):
        return get_object_or_404(ProjectFile, pk=self.kwargs['pk'])

    def get(self, request: Request, *args, **kwargs) -> FileResponse:
        project_file = self.get_object()
        file_handle = project_file.file_path.open()
        response = FileResponse(
            file_handle,
            content_type='application/octet-stream'
        )
        response['Content-Disposition'] = (
            f'attachment; filename="{project_file.file_name}"'
        )
        return response

RegisterUserSerializer — шаблон

from django.contrib.auth.password_validation import validate_password
from django.core.exceptions import ValidationError
import re

class RegisterUserSerializer(serializers.ModelSerializer):
    re_password = serializers.CharField(max_length=128, write_only=True)

    class Meta:
        model = User
        fields = ('username', 'first_name', 'last_name',
                  'email', 'position', 'password', 're_password')
        extra_kwargs = {'password': {'write_only': True}}

    def validate(self, data):
        username = data.get('username')
        first_name = data.get('first_name')
        last_name = data.get('last_name')
        if not re.match('^[a-zA-Z0-9_]*$', username):
            raise serializers.ValidationError("Invalid username")
        if not re.match('^[a-zA-Z]*$', first_name):
            raise serializers.ValidationError("Invalid first_name")
        if not re.match('^[a-zA-Z]*$', last_name):
            raise serializers.ValidationError("Invalid last_name")
        password = data.get("password")
        re_password = data.get("re_password")
        if password != re_password:
            raise serializers.ValidationError({"password": "Passwords don't match"})
        try:
            validate_password(password)
        except ValidationError as err:
            raise serializers.ValidationError({"password": err.messages})
        return data

    def create(self, validated_data):
        password = validated_data.pop('password')
        validated_data.pop('re_password')
        user = User(**validated_data)
        user.set_password(password)
        user.save()
        return user

SlugRelatedField

# Связь по полю email вместо pk
assignee = serializers.SlugRelatedField(
    slug_field='email',
    queryset=User.objects.all(),
    required=False
)

Физическое удаление файла

import os

def delete_file(file_path):
    os.remove(os.path.realpath(file_path))

settings.py — кастомный пользователь

# Добавить ДО первой миграции!
INSTALLED_APPS = [
    ...
    'apps.users',
]

AUTH_USER_MODEL = 'users.User'