Files
APAW/.kilo/skills/python-django-patterns/SKILL.md
¨NW¨ 7445e66676 feat: add Next.js, Vue/Nuxt, React, Python (Django/FastAPI) skills and agents
- python-developer agent: Django/FastAPI backend specialist
- nextjs-patterns skill: App Router, Server Components, Server Actions, Auth.js
- vue-nuxt-patterns skill: Composition API, Pinia, Nitro server, SSR
- react-patterns skill: hooks, Context, TanStack Query, React Hook Form
- python-django-patterns skill: DRF, services, repositories
- python-fastapi-patterns skill: async, Pydantic, SQLAlchemy, dependencies
- /nextjs pipeline command for full-stack Next.js apps
- /vue pipeline command for full-stack Vue/Nuxt apps
- Updated frontend-developer with framework-specific skills
- Updated orchestrator, capability-index for Python + frontend routing
- Updated README, STRUCTURE, EVOLUTION_LOG with all new stacks

Total agents: 30. Stacks: PHP, Next.js, Vue/Nuxt, React, Python, Go, Flutter, Node.js
2026-04-19 10:04:51 +01:00

7.0 KiB

name, description
name description
python-django-patterns Django 5+ patterns — models, views, serializers, REST framework, authentication, management commands

Python Django Patterns

Project Structure

project/
├── manage.py
├── config/                      # Project settings
│   ├── settings/
│   │   ├── base.py
│   │   ├── development.py
│   │   └── production.py
│   ├── urls.py
│   ├── wsgi.py
│   └── asgi.py
├── apps/
│   ├── products/
│   │   ├── models.py
│   │   ├── views.py            # API views (thin)
│   │   ├── serializers.py      # DRF serializers
│   │   ├── urls.py
│   │   ├── services.py         # Business logic
│   │   ├── repositories.py     # Data access
│   │   ├── admin.py
│   │   ├── tasks.py            # Celery tasks
│   │   ├── tests/
│   │   │   ├── test_models.py
│   │   │   ├── test_views.py
│   │   │   └── test_services.py
│   │   └── migrations/
│   ├── orders/
│   └── users/
├── shared/
│   ├── pagination.py
│   ├── permissions.py
│   ├── throttling.py
│   └── exceptions.py
├── requirements/
│   ├── base.txt
│   ├── development.txt
│   └── production.txt
└── docker-compose.yml

Model Pattern

# apps/products/models.py
from django.db import models
from django.urls import reverse


class Product(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=True)
    description = models.TextField(blank=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    category = models.ForeignKey('Category', on_delete=models.PROTECT, related_name='products')
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        ordering = ['-created_at']
        indexes = [
            models.Index(fields=['slug']),
            models.Index(fields=['category', 'is_active']),
        ]

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('product-detail', kwargs={'slug': self.slug})

Service Pattern (Business Logic in services.py)

# apps/products/services.py
from .repositories import ProductRepository


class ProductService:
    def __init__(self, repository=None):
        self.repository = repository or ProductRepository()

    def list_active(self, page=1, per_page=20, category_id=None, search=None):
        return self.repository.list_active(
            page=page, per_page=per_page,
            category_id=category_id, search=search,
        )

    def create(self, data: dict):
        product = self.repository.create(data)
        return product

    def update_price(self, product_id: int, new_price):
        product = self.repository.get_by_id(product_id)
        product.price = new_price
        self.repository.save(product)
        return product

Repository Pattern

# apps/products/repositories.py
from .models import Product


class ProductRepository:
    def list_active(self, page=1, per_page=20, category_id=None, search=None):
        qs = Product.objects.filter(is_active=True).select_related('category')
        if category_id:
            qs = qs.filter(category_id=category_id)
        if search:
            qs = qs.filter(name__icontains=search)
        return qs[(page - 1) * per_page : page * per_page]

    def get_by_id(self, product_id: int):
        return Product.objects.select_related('category').get(pk=product_id)

    def create(self, data: dict):
        return Product.objects.create(**data)

    def save(self, product):
        product.save()
        return product

Serializer Pattern (DRF)

# apps/products/serializers.py
from rest_framework import serializers
from .models import Product, Category


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = ['id', 'name', 'slug']


class ProductListSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)

    class Meta:
        model = Product
        fields = ['id', 'name', 'slug', 'price', 'category', 'is_active']


class ProductDetailSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)

    class Meta:
        model = Product
        fields = '__all__'


class ProductCreateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['name', 'description', 'price', 'category', 'is_active']

    def validate_price(self, value):
        if value <= 0:
            raise serializers.ValidationError('Price must be positive')
        return value

View Pattern (Thin Views)

# apps/products/views.py
from rest_framework import viewsets, filters, status
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Product
from .serializers import ProductListSerializer, ProductDetailSerializer, ProductCreateSerializer
from .services import ProductService
from .repositories import ProductRepository


class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.filter(is_active=True).select_related('category')
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['name', 'description']
    ordering_fields = ['price', 'created_at']

    def get_serializer_class(self):
        if self.action == 'list':
            return ProductListSerializer
        if self.action in ('create', 'update', 'partial_update'):
            return ProductCreateSerializer
        return ProductDetailSerializer

    def get_service(self):
        return ProductService(ProductRepository())

    def create(self, request):
        service = self.get_service()
        product = service.create(request.data)
        return Response(
            ProductDetailSerializer(product).data,
            status=status.HTTP_201_CREATED,
        )

Authentication (DRF + JWT)

# config/settings/base.py
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ],
    'DEFAULT_PAGINATION_CLASS': 'shared.pagination.StandardPagination',
    'PAGE_SIZE': 20,
}

Checklist

  • Fat models, thin views, services for business logic
  • Repository pattern for data access
  • DRF serializers for input validation and output transformation
  • Select_related / prefetch_related to prevent N+1
  • JWT (SimpleJWT) for API authentication
  • Environment-specific settings (base/development/production)
  • Django admin for data management
  • pytest-django for testing
  • Celery for async tasks
  • python manage.py check --deploy before release