Dans mon application Flask, je sers les actifs statiques via l'application dans le dev env, mais j'aimerais utiliser un CDN en production. Chaque actif est chargé dans un modèle appelé base.hmtl, donc je suppose que la solution la plus simple est de passer une variable à la fonction de rendu et de l'utiliser dans le modèle comme:

<script src="{{ STATIC_URL }}/js/main.js"></script>

Normalement, ce serait une chaîne vide dans le dev env, et l'url du cdn en production. Je voudrais éviter de transmettre cette variable STATIC_URL à chaque vue. Je pourrais le faire fonctionner avec

@bp.context_processor
def set_static_path():
    return dict(STATIC_URL='https://foo.bar.com')

Mais pour moi, cela semble un peu hacky. Existe-t-il une meilleure façon de résoudre ce problème?

9
fodma1 6 mars 2016 à 10:45

3 réponses

Meilleure réponse

Il n'est pas nécessaire de modifier la façon dont vous créez un lien vers des fichiers statiques, vous pouvez toujours utiliser url_for('static', filename='myfile.txt'). Remplacez la vue statique par défaut par une vue qui redirige vers le CDN s'il est configuré.

from urllib.parse import urljoin
# or for python 2: from urlparse import urljoin
from flask import redirect

@app.endpoint('static')
def static(filename):
    static_url = app.config.get('STATIC_URL')

    if static_url:
        return redirect(urljoin(static_url, filename))

    return app.send_static_file(filename)

Que vous soyez sur une machine de développement ou de production, définissez la valeur de configuration STATIC_URL sur le CDN et les demandes de fichiers statiques y seront redirigées.


Les redirections sont relativement bon marché et sont mémorisées par les navigateurs. Si vous arrivez au point où les performances en sont affectées de manière significative, vous pouvez écrire une fonction qui établit un lien directement lors de l'utilisation du CDN.

@app.template_global()
def static_url(filename):
    static_url = app.config.get('STATIC_URL')

    if static_url:
        return urljoin(static_url, filename)

    return url_for('static', filename=filename)

Le décorateur template_global rend la fonction disponible dans tous les modèles. Utilisez-le à la place de url_for lorsque vous avez besoin d'URL pour des fichiers statiques.


Il peut y avoir une extension Flask qui le fait déjà pour vous. Par exemple, Flask-S3 fournit un url_for qui sert des fichiers statiques d'AWS S3.

15
davidism 15 janv. 2019 à 14:19

J'ai rencontré un problème similaire en utilisant Flask Assets et Flask-CDN. J'ai trouvé que Flask-CDN essayait et échouait à générer des horodatages pour chaque actif. En cas d'échec, il reviendrait aux URL relatives.

L'ajout de app.config['CDN_TIMESTAMP'] = False a résolu le problème.

0
K. Graves 8 nov. 2018 à 19:34

Ce guide d'intégration de cdn flacon peut valoir la peine d'être lu. Fondamentalement, vous pouvez installer Flask-CDN extension et définir votre URL CDN dans votre fichier app.py comme alors:

from flask import Flask
from flask.ext.cdn import CDN

app = Flask(__name__)
app.config['CDN_DOMAIN'] = 'cdn.yourdomain.com'
CDN(app)
2
CodyA 7 mars 2016 à 14:02