Pourquoi Microservices avec Django ?
Dans un monde où les applications web deviennent de plus en plus complexes et volumineuses, les microservices se sont révélés comme une solution efficace pour gérer la scalabilité, la maintenabilité et la séparation des responsabilités d'une application. En utilisant Django, l'un des frameworks Python les plus populaires, vous pouvez créer des microservices robustes et évolutifs. Dans ce tutoriel, nous allons explorer comment utiliser Django pour développer des microservices efficaces.
Un cas d'usage concret serait le développement d'une plateforme e-commerce, où différents services gèrent les aspects tels que la gestion des produits, l'utilisateur, les paiements et les commandes. En utilisant des microservices basés sur Django, chaque aspect peut être développé, testé et mis à jour indépendamment.
Prerequis
- Connaissance approfondie de Python
- Expérience avec Django (1.8+)
- Compréhension du concept de RESTful API
- Connaissance des bases de données relationnelles
- Familiarité avec le développement asynchrone et la gestion des tâches en arrière-plan
Outils à installer :
- Python 3.x
- Django 4.x
- PostgreSQL ou SQLite
- pip (Python package installer)
- Virtualenv (pour créer un environnement virtuel)
Concepts fondamentaux
1. Architecture Microservices
L'architecture microservices est basée sur le principe de division d'une application en plusieurs services indépendants. Chaque service a une responsabilité spécifique et communique avec les autres via des interfaces RESTful.
Schéma mental :
+-------------------+
| Service Users |
+-------------------+
|
v
+-------------------+
| Service Products |
+-------------------+
|
v
+-------------------+
| Service Orders |
+-------------------+
Code fonctionnel :
## service_users/models.py
from django.db import models
class User(models.Model):
username = models.CharField(max_length=100)
email = models.EmailField()
## service_products/models.py
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
## service_orders/models.py
from django.db import models
class Order(models.Model):
user = models.ForeignKey('service_users.User', on_delete=models.CASCADE)
product = models.ForeignKey('service_products.Product', on_delete=models.CASCADE)
quantity = models.IntegerField()
2. Communication entre Microservices
Les microservices communiquent via des appels HTTP et utilisent des formats de données comme JSON ou YAML. Pour simplifier cette communication, vous pouvez utiliser des bibliothèques comme requests en Python.
Schéma mental :
Service Users -> Service Products <- Service Orders
Code fonctionnel :
## service_orders/views.py
import requests
def create_order(user_id, product_id, quantity):
user_response = requests.get(f'http://service-users/users/{user_id}')
product_response = requests.get(f'http://service-products/products/{product_id}')
if user_response.status_code == 200 and product_response.status_code == 200:
user_data = user_response.json()
product_data = product_response.json()
order = Order.objects.create(
user=user_data,
product=product_data,
quantity=quantity
)
return order
else:
raise Exception('User or Product not found')
3. Gestion des Données avec Django ORM
Chaque service doit avoir sa propre base de données pour éviter les conflits de données et la dépendance. Utilisez le Django ORM pour interagir avec vos bases de données.
Schéma mental :
+-------------------+
| Base de données |
| Service Users |
+-------------------+
+-------------------+
| Base de données |
| Service Products |
+-------------------+
+-------------------+
| Base de données |
| Service Orders |
+-------------------+
Code fonctionnel :
## service_users/urls.py
from django.urls import path
from .views import UserListView, UserDetailView
urlpatterns = [
path('users/', UserListView.as_view(), name='user-list'),
path('users/<int:pk>/', UserDetailView.as_view(), name='user-detail'),
]
## service_products/urls.py
from django.urls import path
from .views import ProductListView, ProductDetailView
urlpatterns = [
path('products/', ProductListView.as_view(), name='product-list'),
path('products/<int:pk>/', ProductDetailView.as_view(), name='product-detail'),
]
Mise en pratique : Projet fil rouge
Mini-Projet : Gestionnaire de Tâches
Nous allons créer un simple gestionnaire de tâches qui permet de créer, lire, mettre à jour et supprimer des tâches. Chaque service aura sa propre base de données.
Étape 1 : Création du Projet Django
django-admin startproject task_manager
cd task_manager
Étape 2 : Ajout des Applications
python manage.py startapp tasks
Étape 3 : Structure des Fichiers
Créez la structure suivante :
task_manager/
├── manage.py
└── task_manager/
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
Étape 4 : Configuration de l'Application Tasks
## tasks/models.py
from django.db import models
class Task(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
completed = models.BooleanField(default=False)
def __str__(self):
return self.title
Étape 5 : Création des Vues et URLS
## tasks/views.py
from django.shortcuts import render, get_object_or_404
from .models import Task
def task_list(request):
tasks = Task.objects.all()
return render(request, 'tasks/task_list.html', {'tasks': tasks})
def task_detail(request, pk):
task = get_object_or_404(Task, pk=pk)
return render(request, 'tasks/task_detail.html', {'task': task})
python
## tasks/urls.py
from django.urls import path
from .views import task_list, task_detail
urlpatterns = [
path('', task_list, name='task-list'),
path('<int:pk>/', task_detail, name='task-detail'),
]
Étape 6 : Configuration du Projet Principal
Ajoutez l'application tasks dans INSTALLED_APPS et configurez les URLS globales.
## task_manager/settings.py
INSTALLED_APPS = [
...
'tasks',
]
ROOT_URLCONF = 'task_manager.urls'
python
## task_manager/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('tasks.urls')),
]
Étape 7 : Création des Templates
Créez les fichiers task_list.html et task_detail.html dans le répertoire templates/tasks/.
<!-- tasks/templates/tasks/task_list.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Task List</title>
</head>
<body>
<h1>Tasks</h1>
<ul>
{% for task in tasks %}
<li>task.title</li>
{% endfor %}
</ul>
</body>
</html>
html
<!-- tasks/templates/tasks/task_detail.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Task Detail</title>
</head>
<body>
<h1>task.title</h1>
<p>task.description</p>
<p>Status: task.completed|yesno:"Completed,Not Completed"</p>
</body>
</html>
Étape 8 : Migrations et Création des Bases de Données
python manage.py makemigrations
python manage.py migrate
Étape 9 : Lancement du Serveur
python manage.py runserver
Accédez à http://127.0.0.1:8000/ pour voir le gestionnaire de tâches en action.
Erreurs fréquentes et debugging
1. Erreur : AttributeError: 'User' object has no attribute 'username'
## ❌ Mauvais
user.username = user_data['name']
## ✅ Correct
user.username = user_data.get('username', '')
2. Erreur : DoesNotExist lors de la récupération d'un objet
## ❌ Mauvais
user = User.objects.get(username=user_data['username'])
## ✅ Correct
try:
user = User.objects.get(username=user_data['username'])
except User.DoesNotExist:
raise Exception('User not found')
3. Erreur : ConnectionRefusedError lors de l'appel à un service distant
## ❌ Mauvais
response = requests.get(f'http://service-users/users/{user_id}')
## ✅ Correct
import time
max_retries = 5
retry_delay = 2
for _ in range(max_retries):
try:
response = requests.get(f'http://service-users/users/{user_id}')
break
except ConnectionRefusedError:
time.sleep(retry_delay)
else:
raise Exception('Service Users is not available')
Pour aller plus loin
Gestion des Événements Asynchrones : Utilisez Django Channels pour gérer les événements en temps réel et les notifications.
Sécurité avec OAuth 2.0 : Intégrez OAuth 2.0 pour une authentification sécurisée entre les microservices.
Tests Unitaires et d'Intégration : Utilisez Django's testing framework pour écrire des tests unitaires et d'intégration pour vos microservices.
Défi Pratique
Créez un service de notification qui envoie une alerte email lorsque l'état d'une tâche change. Utilisez Django's built-in send_mail function pour envoyer les emails.
Bonne chance avec votre projet !