Skip to main content

django-development

Django framework workflow guidelines. Activate when working with Django projects, manage.py, django-admin, or Django-specific patterns.

Datos de origen

Repositorio
zekdevs/pi-config
Última actividad en el origen
17 de mayo de 2026 a las 04:55
Idioma detectado de SKILL.md
inglés
Estrellas
34
Forks
3

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
django-development
description
Django framework workflow guidelines. Activate when working with Django projects, manage.py, django-admin, or Django-specific patterns.
# Django Workflow ## Django 5.x Features ### Composite Primary Keys (Django 5.2+) Django 5.2 introduces native composite primary key support. You SHOULD use `CompositePrimaryKey` for junction tables and legacy database integration: ```python from django.db import models class OrderItem(models.Model): order = models.ForeignKey("Order", on_delete=models.CASCADE) product = models.ForeignKey("Product", on_delete=models.CASCADE) quantity = models.PositiveIntegerField() class Meta: constraints = [ models.CompositePrimaryKey("order", "product"), ] ``` ### Async Views You SHOULD prefer async views for I/O-bound operations. Django 5.x has improved async ORM support: ```python from django.http import JsonResponse async def fetch_items(request): items = [item async for item in Item.objects.filter(active=True)] return JsonResponse({"items": [i.name for i in items]}) ``` Key async patterns: - Use `async for` with QuerySets - Use `await` with `aget()`, `afirst()`, `acount()`, `aexists()` - Sync ORM calls in async views trigger `SynchronousOnlyOperation` exceptions ### Django Tasks (Background Tasks) For simple background tasks, you MAY use Django's built-in task system (Django 5.1+): ```python from django.tasks import task @task def send_welcome_email(user_id: int) -> None: user = User.objects.get(pk=user_id) # Send email logic ``` For complex workflows, Celery remains RECOMMENDED. --- ## Architecture Patterns ### Fat Models to Services Pattern Business logic MUST NOT reside in views. You MUST use the services pattern: ```python # services/order_service.py from dataclasses import dataclass from decimal import Decimal from django.db import transaction @dataclass class OrderService: """Order-related business operations.""" @staticmethod @transaction.atomic def create_order(user, cart_items: list) -> "Order": """Create order from cart items with inventory validation.""" order = Order.objects.create(user=user, status=Order.Status.PENDING) for item in cart_items: if item.product.stock < item.quantity: raise InsufficientStockError(item.product) OrderItem.objects.create( order=order, product=item.product, quantity=item.quantity, price=item.product.price, ) item.product.stock -= item.quantity item.product.save(update_fields=["stock"]) return order @staticmethod def calculate_total(order: "Order") -> Decimal: """Calculate order total with discounts applied.""" return sum(item.subtotal for item in order.items.all()) ``` ### Selectors Pattern Query logic MUST be encapsulated in selectors. Views MUST NOT contain complex querysets: ```python # selectors/product_selectors.py from django.db.models import QuerySet, Q, Prefetch class ProductSelectors: """Product query encapsulation.""" @staticmethod def get_active_products() -> QuerySet: return Product.objects.filter( is_active=True, stock__gt=0, ).select_related("category") @staticmethod def search_products(query: str) -> QuerySet: return Product.objects.filter( Q(name__icontains=query) | Q(description__icontains=query), is_active=True, ) @staticmethod def get_product_with_reviews(product_id: int) -> Product: return Product.objects.prefetch_related( Prefetch( "reviews", queryset=Review.objects.filter(approved=True).order_by("-created_at"), ) ).get(pk=product_id) ``` --- ## Views ### Class-Based vs Function-Based Views You SHOULD use CBVs for standard CRUD operations and FBVs for simple, one-off logic: **Use CBVs when:** - Standard CRUD operations - Pagination, filtering, or sorting needed - Template rendering with context - Code reuse via mixins **Use FBVs when:** - Simple API endpoints - Webhooks or callbacks - Complex conditional logic that doesn't fit CBV flow ### CBV Example ```python from django.views.generic import ListView, DetailView from django.contrib.auth.mixins import LoginRequiredMixin class ProductListView(ListView): model = Product template_name = "products/list.html" context_object_name = "products" paginate_by = 20 def get_queryset(self): return ProductSelectors.get_active_products() class ProductDetailView(DetailView): model = Product template_name = "products/detail.html" slug_url_kwarg = "slug" def get_object(self): return ProductSelectors.get_product_with_reviews(self.kwargs["slug"]) ``` --- --- ## Testing ### Test Organization ```python # tests/test_services/test_order_service.py import pytest from decimal import Decimal from apps.orders.services import OrderService @pytest.mark.django_db class TestOrderService: def test_create_order_success(self, user, cart_with_items): order = OrderService.create_order(user, cart_with_items) assert order.user == user assert order.items.count() == len(cart_with_items) def test_create_order_insufficient_stock(self, user, cart_with_unavailable_item): with pytest.raises(InsufficientStockError): OrderService.create_order(user, cart_with_unavailable_item) ``` ### Fixtures ```python # conftest.py import pytest from django.contrib.auth import get_user_model @pytest.fixture def user(db): User = get_user_model() return User.objects.create_user( email="test@example.com", password="testpass123", ) @pytest.fixture def product(db, category): return Product.objects.create( name="Test Product", slug="test-product", category=category, price=Decimal("29.99"), stock=10, ) ``` ---
Ver en GitHub