Redis
 sql >> Base de données >  >> NoSQL >> Redis

flacon python comment passer un paramètre dynamique à un décorateur

Si nous vérifions les docs pour flask application global, flask.g , il dit :

Pour partager des données valides pour une seule requête d'une fonction à une autre, une variable globale n'est pas suffisante car elle se briserait dans les environnements threadés. Flask vous fournit un objet spécial qui garantit qu'il n'est valide que pour la demande active et cela renverra des valeurs différentes pour chaque requête.

Ceci est réalisé en utilisant un proxy local de thread (dans flask/globals.py ):

g = LocalProxy(partial(_lookup_app_object, 'g'))

L'autre chose que nous devons garder à l'esprit est que Python exécute la première passe de notre décorateur pendant la phase de "compilation", en dehors de toute requête, ou flask application. Cela signifie key l'argument se voit attribuer une valeur de 'shop_{}_style'.format(g.city.id) lorsque votre application démarre (lorsque votre classe est analysée/décorée), en dehors de flask contexte de la requête.

Mais nous pouvons facilement retarder l'accès à flask.g en utilisant un proxy paresseux, qui récupère la valeur uniquement lorsqu'il est utilisé, via la fonction de rappel. Utilisons celui déjà fourni avec flask , le werkzeug.local.LocalProxy :

from werkzeug.local import LocalProxy

class ShopAreaAndStyleListAPI(Resource):
    @redis_hash_shop_style(key=LocalProxy(lambda: 'shop_{}_style'.format(g.city.id)))
    def get(self):
        # if not found from redis, query from mysql
        pass

En général (pour non-flask ou non werkzeug apps), nous pouvons utiliser un LazyProxy similaire à partir des ProxyTypes paquet.

Sans rapport avec cela, vous voudrez également corriger votre redis_hash_shop_style décorateur non seulement pour récupérer à partir de redis , mais aussi pour mettre à jour (ou créer) la valeur si périmée (ou inexistante), en appelant le f() enveloppé le cas échéant.