Flask - Concepts Avancés

Explorez les fonctionnalités avancées de Flask pour construire des applications web robustes et scalables.

Blueprints

Les Blueprints permettent d'organiser une application en composants réutilisables.

# auth/routes.py
from flask import Blueprint

auth = Blueprint('auth', __name__)

@auth.route('/login')
def login():
    return 'Page de connexion'

# app/__init__.py
from flask import Flask
from .auth.routes import auth

app = Flask(__name__)
app.register_blueprint(auth, url_prefix='/auth')

Authentification

from flask_login import (
    LoginManager,
    UserMixin,
    login_required
)

login_manager = LoginManager()
login_manager.init_app(app)

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80))

@login_required
def profile():
    return 'Page protégée'

API RESTful

Définition de l'API

from flask_restful import (
    Resource, Api, reqparse
)

api = Api(app)

class UserAPI(Resource):
    def get(self, user_id):
        user = User.query.get(user_id)
        return user.to_dict()

    def put(self, user_id):
        args = parser.parse_args()
        user = User.query.get(user_id)
        user.update(args)
        return user.to_dict()

api.add_resource(UserAPI,
    '/api/users/')

Sérialisation

from flask_marshmallow import (
    Marshmallow,
    fields
)

ma = Marshmallow(app)

class UserSchema(ma.Schema):
    id = fields.Int(dump_only=True)
    username = fields.Str()
    email = fields.Email()

user_schema = UserSchema()

Tests

def test_home_page():
    client = app.test_client()
    response = client.get('/')
    assert response.status_code == 200

def test_create_user():
    client = app.test_client()
    response = client.post('/users',
        json={'username': 'test'})
    assert response.status_code == 201

Gestion des erreurs

@app.errorhandler(404)
def not_found(error):
    return {
        'error': 'Resource not found'
    }, 404

class APIError(Exception):
    status_code = 400

@app.errorhandler(APIError)
def handle_api_error(error):
    return {
        'error': str(error)
    }, error.status_code

Bonnes pratiques avancées

  • Configuration par environnement
    config = {
        'development': DevConfig,
        'production': ProdConfig,
        'testing': TestConfig
    }[os.getenv('FLASK_ENV', 'development')]
  • Migrations de base de données
    flask db init
    flask db migrate -m "Initial migration"
    flask db upgrade
  • Caching
    from flask_caching import Cache
    
    cache = Cache(app)
    
    @cache.memoize(timeout=300)
    def get_user(user_id):
        return User.query.get(user_id)