Retour à la communauté

Construire une Architecture Django Scalable: Structures de Projet Professionnelles

MEME 07 Mar 2026
#Django #Python #scalability

Construire une Architecture Django Scalable: Structures de Projet Professionnelles

La structure de votre projet Django impacte directement sa maintenabilité et scalabilité. Découvrez comment organiser votre code comme les pros.

Structure Recommandée (Production Ready)

mon_projet/
├── config/ # Configuration globale
│ ├── settings/
│ │ ├── base.py # Settings partagés
│ │ ├── development.py # Dev settings
│ │ ├── production.py # Prod settings
│ │ └── testing.py # Test settings
│ ├── urls.py
│ ├── wsgi.py
│ └── asgi.py

├── apps/
│ ├── users/ # App utilisateurs
│ │ ├── models.py
│ │ ├── views.py
│ │ ├── serializers.py # Pour API
│ │ ├── urls.py
│ │ ├── tests/
│ │ └── migrations/
│ │
│ ├── posts/ # App posts
│ ├── comments/ # App commentaires
│ └── core/ # App core
│ ├── models.py # Modèles partagés
│ ├── mixins.py # Mixins réutilisables
│ └── utils.py # Utilitaires

├── templates/
│ ├── base.html
│ └── users/
│ ├── list.html
│ └── detail.html

├── static/
│ ├── css/
│ ├── js/
│ └── images/

├── media/ # Fichiers uploadés

├── tests/ # Tests globaux
│ ├── test_models.py
│ └── test_views.py

├── scripts/ # Scripts de gestion
│ ├── populate_db.py
│ └── cleanup.py

├── docker/ # Configuration Docker
│ ├── Dockerfile
│ └── docker-compose.yml

├── .env.example # Template des variables
├── manage.py
├── requirements.txt
├── requirements-dev.txt
└── README.md

Architecture des Apps
Models (Bien Organisé)
# apps/core/models.py - Modèle de base
from django.db import models

class TimeStampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
abstract = True

# apps/users/models.py
from apps.core.models import TimeStampedModel

class User(TimeStampedModel):
email = models.EmailField(unique=True)
name = models.CharField(max_length=255)
is_active = models.BooleanField(default=True)

class Meta:
db_table = 'users'
indexes = [
models.Index(fields=['email']),
]

def __str__(self):
return self.name

Services (Logique Métier)
# apps/users/services.py
class UserService:
@staticmethod
def create_user(email, name, password):
"""Créer un utilisateur avec validation"""
if User.objects.filter(email=email).exists():
raise ValueError("Email déjà utilisé")

user = User.objects.create_user(
email=email,
name=name,
password=password
)
return user

@staticmethod
def get_user_with_posts(user_id):
"""Récupérer un utilisateur avec ses posts (optimisé)"""
return User.objects.select_related('profile')\
.prefetch_related('posts')\
.get(id=user_id)

Views (REST API)

# apps/users/views.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import action
from rest_framework.response import Response

class UserViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
filterset_fields = ['is_active']
ordering_fields = ['created_at', 'name']

@action(detail=True, methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)

if serializer.is_valid():
user.set_password(serializer.data['password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors, status=400)

def get_queryset(self):
"""Optimiser les queries selon l'action"""
if self.action == 'list':
return self.queryset.only('id', 'name', 'email')
elif self.action == 'retrieve':
return self.queryset.select_related('profile')
return self.queryset

Serializers

# apps/users/serializers.py
from rest_framework import serializers
from .models import User

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'email', 'name', 'created_at']
read_only_fields = ['created_at']

class UserDetailSerializer(UserSerializer):
posts_count = serializers.SerializerMethodField()

class Meta(UserSerializer.Meta):
fields = UserSerializer.Meta.fields + ['posts_count']

def get_posts_count(self, obj):
return obj.posts.count()

Settings Professionnels

# config/settings/base.py
import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent.parent

SECRET_KEY = os.getenv('SECRET_KEY')
DEBUG = os.getenv('DEBUG', 'False') == 'True'
ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', 'localhost').split(',')

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
# ...
'rest_framework',
'corsheaders',
'apps.users',
'apps.posts',
'apps.comments',
]

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'corsheaders.middleware.CorsMiddleware',
# ...
]

# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME'),
'USER': os.getenv('DB_USER'),
'PASSWORD': os.getenv('DB_PASSWORD'),
'HOST': os.getenv('DB_HOST'),
'PORT': os.getenv('DB_PORT', '5432'),
}
}

# Cache
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': os.getenv('REDIS_URL', 'redis://127.0.0.1:6379/1'),
}
}

# REST Framework
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20,
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
}

Testing Professionnel

# tests/test_users.py
from django.test import TestCase
from apps.users.models import User
from apps.users.services import UserService

class UserServiceTestCase(TestCase):
def setUp(self):
self.user_data = {
'email': 'test@example.com',
'name': 'Test User',
'password': 'securepass123'
}

def test_create_user(self):
user = UserService.create_user(**self.user_data)
self.assertEqual(user.email, self.user_data['email'])

def test_duplicate_email(self):
UserService.create_user(**self.user_data)
with self.assertRaises(ValueError):
UserService.create_user(**self.user_data)

def test_get_user_optimization(self):
user = UserService.get_user_with_posts(1)
# Vérifier que les requêtes sont optimisées

Points Clés pour la Scalabilité

Séparation des responsabilités - Models, Services, Views distincts Settings multiples - Dev, Prod, Testing séparés Query optimization - select_related, prefetch_related Caching - Redis pour cache/sessions Testing - Couverture complète Logging - Monitoring en production Serializers - Validation stricte

Questions pour la Communauté

Comment organisez-vous vos grands projets Django?
Utilisez-vous Celery pour les tasks asynchrones?
Avez-vous des patterns Django particuliers à partager?
Partagez vos architectures!

0 Réponses

Aucune réponse pour le moment. Soyez le premier à répondre !

Veuillez vous connecter pour participer à la discussion.