mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-04-12 20:53:34 +08:00
docs(pt-BR): add examples translation
This commit is contained in:
308
docs/pt-BR/examples/django-api-CLAUDE.md
Normal file
308
docs/pt-BR/examples/django-api-CLAUDE.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# Django REST API — CLAUDE.md de Projeto
|
||||
|
||||
> Exemplo real para uma API Django REST Framework com PostgreSQL e Celery.
|
||||
> Copie para a raiz do seu projeto e customize para seu serviço.
|
||||
|
||||
## Visão Geral do Projeto
|
||||
|
||||
**Stack:** Python 3.12+, Django 5.x, Django REST Framework, PostgreSQL, Celery + Redis, pytest, Docker Compose
|
||||
|
||||
**Arquitetura:** Design orientado a domínio com apps por domínio de negócio. DRF para camada de API, Celery para tarefas assíncronas, pytest para testes. Todos os endpoints retornam JSON — sem renderização de templates.
|
||||
|
||||
## Regras Críticas
|
||||
|
||||
### Convenções Python
|
||||
|
||||
- Type hints em todas as assinaturas de função — use `from __future__ import annotations`
|
||||
- Sem `print()` statements — use `logging.getLogger(__name__)`
|
||||
- f-strings para formatação, nunca `%` ou `.format()`
|
||||
- Use `pathlib.Path` e não `os.path` para operações de arquivo
|
||||
- Imports ordenados com isort: stdlib, third-party, local (enforced by ruff)
|
||||
|
||||
### Banco de Dados
|
||||
|
||||
- Todas as queries usam Django ORM — SQL bruto só com `.raw()` e queries parametrizadas
|
||||
- Migrations versionadas no git — nunca use `--fake` em produção
|
||||
- Use `select_related()` e `prefetch_related()` para prevenir queries N+1
|
||||
- Todos os models devem ter auto-fields `created_at` e `updated_at`
|
||||
- Índices em qualquer campo usado em `filter()`, `order_by()` ou cláusulas `WHERE`
|
||||
|
||||
```python
|
||||
# BAD: N+1 query
|
||||
orders = Order.objects.all()
|
||||
for order in orders:
|
||||
print(order.customer.name) # hits DB for each order
|
||||
|
||||
# GOOD: Single query with join
|
||||
orders = Order.objects.select_related("customer").all()
|
||||
```
|
||||
|
||||
### Autenticação
|
||||
|
||||
- JWT via `djangorestframework-simplejwt` — access token (15 min) + refresh token (7 days)
|
||||
- Permission classes em toda view — nunca confiar no padrão
|
||||
- Use `IsAuthenticated` como base e adicione permissões customizadas para acesso por objeto
|
||||
- Token blacklisting habilitado para logout
|
||||
|
||||
### Serializers
|
||||
|
||||
- Use `ModelSerializer` para CRUD simples, `Serializer` para validação complexa
|
||||
- Separe serializers de leitura e escrita quando input/output diferirem
|
||||
- Valide no nível de serializer, não na view — views devem ser enxutas
|
||||
|
||||
```python
|
||||
class CreateOrderSerializer(serializers.Serializer):
|
||||
product_id = serializers.UUIDField()
|
||||
quantity = serializers.IntegerField(min_value=1, max_value=100)
|
||||
|
||||
def validate_product_id(self, value):
|
||||
if not Product.objects.filter(id=value, active=True).exists():
|
||||
raise serializers.ValidationError("Product not found or inactive")
|
||||
return value
|
||||
|
||||
class OrderDetailSerializer(serializers.ModelSerializer):
|
||||
customer = CustomerSerializer(read_only=True)
|
||||
product = ProductSerializer(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = Order
|
||||
fields = ["id", "customer", "product", "quantity", "total", "status", "created_at"]
|
||||
```
|
||||
|
||||
### Tratamento de Erro
|
||||
|
||||
- Use DRF exception handler para respostas de erro consistentes
|
||||
- Exceções customizadas de regra de negócio em `core/exceptions.py`
|
||||
- Nunca exponha detalhes internos de erro para clientes
|
||||
|
||||
```python
|
||||
# core/exceptions.py
|
||||
from rest_framework.exceptions import APIException
|
||||
|
||||
class InsufficientStockError(APIException):
|
||||
status_code = 409
|
||||
default_detail = "Insufficient stock for this order"
|
||||
default_code = "insufficient_stock"
|
||||
```
|
||||
|
||||
### Estilo de Código
|
||||
|
||||
- Sem emojis em código ou comentários
|
||||
- Tamanho máximo de linha: 120 caracteres (enforced by ruff)
|
||||
- Classes: PascalCase, funções/variáveis: snake_case, constantes: UPPER_SNAKE_CASE
|
||||
- Views enxutas — lógica de negócio em funções de serviço ou métodos do model
|
||||
|
||||
## Estrutura de Arquivos
|
||||
|
||||
```
|
||||
config/
|
||||
settings/
|
||||
base.py # Shared settings
|
||||
local.py # Dev overrides (DEBUG=True)
|
||||
production.py # Production settings
|
||||
urls.py # Root URL config
|
||||
celery.py # Celery app configuration
|
||||
apps/
|
||||
accounts/ # User auth, registration, profile
|
||||
models.py
|
||||
serializers.py
|
||||
views.py
|
||||
services.py # Business logic
|
||||
tests/
|
||||
test_views.py
|
||||
test_services.py
|
||||
factories.py # Factory Boy factories
|
||||
orders/ # Order management
|
||||
models.py
|
||||
serializers.py
|
||||
views.py
|
||||
services.py
|
||||
tasks.py # Celery tasks
|
||||
tests/
|
||||
products/ # Product catalog
|
||||
models.py
|
||||
serializers.py
|
||||
views.py
|
||||
tests/
|
||||
core/
|
||||
exceptions.py # Custom API exceptions
|
||||
permissions.py # Shared permission classes
|
||||
pagination.py # Custom pagination
|
||||
middleware.py # Request logging, timing
|
||||
tests/
|
||||
```
|
||||
|
||||
## Padrões-Chave
|
||||
|
||||
### Camada de Serviço
|
||||
|
||||
```python
|
||||
# apps/orders/services.py
|
||||
from django.db import transaction
|
||||
|
||||
def create_order(*, customer, product_id: uuid.UUID, quantity: int) -> Order:
|
||||
"""Create an order with stock validation and payment hold."""
|
||||
product = Product.objects.select_for_update().get(id=product_id)
|
||||
|
||||
if product.stock < quantity:
|
||||
raise InsufficientStockError()
|
||||
|
||||
with transaction.atomic():
|
||||
order = Order.objects.create(
|
||||
customer=customer,
|
||||
product=product,
|
||||
quantity=quantity,
|
||||
total=product.price * quantity,
|
||||
)
|
||||
product.stock -= quantity
|
||||
product.save(update_fields=["stock", "updated_at"])
|
||||
|
||||
# Async: send confirmation email
|
||||
send_order_confirmation.delay(order.id)
|
||||
return order
|
||||
```
|
||||
|
||||
### Padrão de View
|
||||
|
||||
```python
|
||||
# apps/orders/views.py
|
||||
class OrderViewSet(viewsets.ModelViewSet):
|
||||
permission_classes = [IsAuthenticated]
|
||||
pagination_class = StandardPagination
|
||||
|
||||
def get_serializer_class(self):
|
||||
if self.action == "create":
|
||||
return CreateOrderSerializer
|
||||
return OrderDetailSerializer
|
||||
|
||||
def get_queryset(self):
|
||||
return (
|
||||
Order.objects
|
||||
.filter(customer=self.request.user)
|
||||
.select_related("product", "customer")
|
||||
.order_by("-created_at")
|
||||
)
|
||||
|
||||
def perform_create(self, serializer):
|
||||
order = create_order(
|
||||
customer=self.request.user,
|
||||
product_id=serializer.validated_data["product_id"],
|
||||
quantity=serializer.validated_data["quantity"],
|
||||
)
|
||||
serializer.instance = order
|
||||
```
|
||||
|
||||
### Padrão de Teste (pytest + Factory Boy)
|
||||
|
||||
```python
|
||||
# apps/orders/tests/factories.py
|
||||
import factory
|
||||
from apps.accounts.tests.factories import UserFactory
|
||||
from apps.products.tests.factories import ProductFactory
|
||||
|
||||
class OrderFactory(factory.django.DjangoModelFactory):
|
||||
class Meta:
|
||||
model = "orders.Order"
|
||||
|
||||
customer = factory.SubFactory(UserFactory)
|
||||
product = factory.SubFactory(ProductFactory, stock=100)
|
||||
quantity = 1
|
||||
total = factory.LazyAttribute(lambda o: o.product.price * o.quantity)
|
||||
|
||||
# apps/orders/tests/test_views.py
|
||||
import pytest
|
||||
from rest_framework.test import APIClient
|
||||
|
||||
@pytest.mark.django_db
|
||||
class TestCreateOrder:
|
||||
def setup_method(self):
|
||||
self.client = APIClient()
|
||||
self.user = UserFactory()
|
||||
self.client.force_authenticate(self.user)
|
||||
|
||||
def test_create_order_success(self):
|
||||
product = ProductFactory(price=29_99, stock=10)
|
||||
response = self.client.post("/api/orders/", {
|
||||
"product_id": str(product.id),
|
||||
"quantity": 2,
|
||||
})
|
||||
assert response.status_code == 201
|
||||
assert response.data["total"] == 59_98
|
||||
|
||||
def test_create_order_insufficient_stock(self):
|
||||
product = ProductFactory(stock=0)
|
||||
response = self.client.post("/api/orders/", {
|
||||
"product_id": str(product.id),
|
||||
"quantity": 1,
|
||||
})
|
||||
assert response.status_code == 409
|
||||
|
||||
def test_create_order_unauthenticated(self):
|
||||
self.client.force_authenticate(None)
|
||||
response = self.client.post("/api/orders/", {})
|
||||
assert response.status_code == 401
|
||||
```
|
||||
|
||||
## Variáveis de Ambiente
|
||||
|
||||
```bash
|
||||
# Django
|
||||
SECRET_KEY=
|
||||
DEBUG=False
|
||||
ALLOWED_HOSTS=api.example.com
|
||||
|
||||
# Database
|
||||
DATABASE_URL=postgres://user:pass@localhost:5432/myapp
|
||||
|
||||
# Redis (Celery broker + cache)
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
|
||||
# JWT
|
||||
JWT_ACCESS_TOKEN_LIFETIME=15 # minutes
|
||||
JWT_REFRESH_TOKEN_LIFETIME=10080 # minutes (7 days)
|
||||
|
||||
# Email
|
||||
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
|
||||
EMAIL_HOST=smtp.example.com
|
||||
```
|
||||
|
||||
## Estratégia de Teste
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pytest --cov=apps --cov-report=term-missing
|
||||
|
||||
# Run specific app tests
|
||||
pytest apps/orders/tests/ -v
|
||||
|
||||
# Run with parallel execution
|
||||
pytest -n auto
|
||||
|
||||
# Only failing tests from last run
|
||||
pytest --lf
|
||||
```
|
||||
|
||||
## Workflow ECC
|
||||
|
||||
```bash
|
||||
# Planning
|
||||
/plan "Add order refund system with Stripe integration"
|
||||
|
||||
# Development with TDD
|
||||
/tdd # pytest-based TDD workflow
|
||||
|
||||
# Review
|
||||
/python-review # Python-specific code review
|
||||
/security-scan # Django security audit
|
||||
/code-review # General quality check
|
||||
|
||||
# Verification
|
||||
/verify # Build, lint, test, security scan
|
||||
```
|
||||
|
||||
## Fluxo Git
|
||||
|
||||
- `feat:` novas features, `fix:` correções de bug, `refactor:` mudanças de código
|
||||
- Branches de feature a partir da `main`, PRs obrigatórios
|
||||
- CI: ruff (lint + format), mypy (types), pytest (tests), safety (dep check)
|
||||
- Deploy: imagem Docker, gerenciada via Kubernetes ou Railway
|
||||
Reference in New Issue
Block a user