Comment Créer une API REST Professionnelle avec Flask
Flask est léger mais très puissant pour créer des APIs. Voici comment faire les choses correctement.
mon_api/
├── app.py
├── models/
│ ├── user.py
│ └── article.py
├── routes/
│ ├── users.py
│ ├── articles.py
│ └── auth.py
├── services/
│ ├── user_service.py
│ └── auth_service.py
└── requirements.txt
Installation
pip install flask flask-sqlalchemy flask-marshmallow flask-cors python-dotenv
Configuration de Base
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS
import os
app = Flask(__name__)
CORS(app)
# Configuration
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DATABASE_URL')
app.config['JSON_SORT_KEYS'] = False
db = SQLAlchemy(app)
Modèles
from datetime import datetime
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, nullable=False)
name = db.Column(db.String(120), nullable=False)
password_hash = db.Column(db.String(255))
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def to_dict(self):
return {
'id': self.id,
'email': self.email,
'name': self.name,
'created_at': self.created_at.isoformat()
}
Routes (Endpoints)
from flask import Blueprint, request, jsonify
from models.user import User
from db import db
users_bp = Blueprint('users', __name__, url_prefix='/api/v1/users')
@users_bp.route('', methods=['GET'])
def get_users():
page = request.args.get('page', 1, type=int)
users = User.query.paginate(page=page, per_page=10)
return jsonify({
'data': [u.to_dict() for u in users.items],
'total': users.total,
'pages': users.pages
})
@users_bp.route('/<int:user_id>', methods=['GET'])
def get_user(user_id):
user = User.query.get_or_404(user_id)
return jsonify(user.to_dict())
@users_bp.route('', methods=['POST'])
def create_user():
data = request.get_json()
# Validation
if not data.get('email') or not data.get('name'):
return jsonify({'error': 'Email et name requis'}), 400
if User.query.filter_by(email=data['email']).first():
return jsonify({'error': 'Email déjà utilisé'}), 409
user = User(email=data['email'], name=data['name'])
db.session.add(user)
db.session.commit()
return jsonify(user.to_dict()), 201
@users_bp.route('/<int:user_id>', methods=['PUT'])
def update_user(user_id):
user = User.query.get_or_404(user_id)
data = request.get_json()
if 'name' in data:
user.name = data['name']
db.session.commit()
return jsonify(user.to_dict())
@users_bp.route('/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
return '', 204
# Enregistrer le blueprint
app.register_blueprint(users_bp)
Gestion des Erreurs
@app.errorhandler(404)
def not_found(error):
return jsonify({'error': 'Ressource non trouvée'}), 404
@app.errorhandler(500)
def internal_error(error):
db.session.rollback()
return jsonify({'error': 'Erreur serveur'}), 500
Authentification JWT
pip install flask-jwt-extended
from flask_jwt_extended import JWTManager, create_access_token, jwt_required
app.config['JWT_SECRET_KEY'] = os.getenv('JWT_SECRET_KEY')
jwt = JWTManager(app)
@app.route('/api/v1/auth/login', methods=['POST'])
def login():
data = request.get_json()
user = User.query.filter_by(email=data['email']).first()
if not user or not user.check_password(data['password']):
return jsonify({'error': 'Identifiants invalides'}), 401
access_token = create_access_token(identity=user.id)
return jsonify({'access_token': access_token})
@app.route('/api/v1/protected', methods=['GET'])
@jwt_required()
def protected_route():
current_user_id = get_jwt_identity()
return jsonify({'message': f'User {current_user_id}'})
Déploiement
# Avec Gunicorn
pip install gunicorn
gunicorn -w 4 -b 0.0.0.0:5000 app:app
Aucun commentaire pour le moment. Soyez le premier !