web-dev-qa-db-fra.com

Python Django Variables globales

Je recherche un moyen simple mais recommandé dans Django pour stocker une variable en mémoire uniquement. Lorsque Apache redémarre ou que le serveur de développement Django redémarre, la variable est réinitialisé à 0. Plus précisément, je veux compter le nombre de fois qu'une action particulière a lieu sur chaque instance de modèle (enregistrement de base de données), mais pour des raisons de performances, je ne veux pas stocker ces nombres dans la base de données. t fais attention si les décomptes disparaissent après un redémarrage du serveur. Mais tant que le serveur est en fonction, je veux que ces décomptes soient cohérents entre le Django Shell et l'interface web, et je veux être capable de retourner combien de fois l'action a eu lieu sur chaque instance de modèle.

Je ne veux pas que les variables soient associées à un utilisateur ou à une session car je pourrais vouloir renvoyer ces décomptes sans être connecté (et je veux que les décomptes soient cohérents quel que soit l'utilisateur connecté). Suis-je en train de décrire une variable globale? Si oui, comment en utiliser un dans Django? J'ai remarqué que les fichiers comme urls.py, settings.py et models.py ne semblent être analysés qu'une seule fois par démarrage du serveur (contrairement à views.py qui semble être analysé à chaque demande). Est-ce à dire que je devrais déclarer mes variables dans l'un de ces fichiers? Ou devrais-je le stocker dans un attribut de modèle d'une manière ou d'une autre (tant qu'il reste en place aussi longtemps que le serveur fonctionne)? C'est probablement une question facile, mais je ne sais pas comment cela se fait dans Django.

Tout commentaire ou conseil est très apprécié. Merci, Joe

42
Joe J

Vous ne devez pas déclarer des variables globales. Les paramètres (constantes) sont OK s'ils sont bien faits. Mais les variables violent avec l'architecture shared-nothing et peuvent causer beaucoup de problèmes. (dans le meilleur des cas, ils seront incohérents)

Je voudrais simplement stocker ces statistiques dans le cache. (Eh bien, en fait, je les stocke dans la base de données, mais vous avez précisé que vous croyez cela aura un impact négatif sur les performances, donc ...)

Les nouvelles méthodes incr() et decr() sont particulièrement adaptées au comptage. Voir docs pour plus d'informations.

25
muhuk

Pourquoi on ne doit pas déclarer des variables globales? O_o. Cela ressemble à une propagande. Si l'auteur sait ce qu'il veut et quels seront les effets secondaires, pourquoi pas. C'est peut-être juste une expérience rapide.

Vous pouvez déclarer votre compteur en tant que membre modèle de classe -. Ensuite, pour faire face à la condition de concurrence, vous devez ajouter une méthode qui attendra si un autre client, d'un autre thread fonctionne avec le compteur. Quelque chose comme ça:

import threading

class MyModel(ModelBase):
    _counter = 0
    _counter_lock = threading.Lock()

    @classmethod
    def increment_counter(cls):
        with cls._counter_lock:
            cls._counter += 1

    def some_action(self):
        # core code
        self.increment_counter()


# somewhere else
print MyModel._counter

N'oubliez pas cependant: vous devez avoir votre application en un processus . Donc, si vous avez déployé l'application sous Apache, assurez-vous qu'elle est configurée pour générer de nombreux threads, mais pas beaucoup de processus. Si vous expérimentez avec ./manage.py run aucune action n'est requise.

63
nkrkv

Si vous voulez éviter les tracas avec la base de données Django, par exemple les migrations ou les problèmes de performances, vous pouvez envisager la base de données en mémoire redis . Redis garantit la cohérence même s'il existe plusieurs Django processus.

0
Juuso Ohtonen