2010-04-21 13 views
35

Sto cercando il modo semplice ma consigliato in Django di memorizzare una variabile solo in memoria. Al riavvio di Apache o al riavvio del server di sviluppo Django, la variabile viene reimpostata su 0. In particolare, voglio contare quante volte una particolare azione ha luogo su ogni istanza di modello (record del database), ma per motivi di prestazioni, non lo faccio t voglio memorizzare questi conteggi nel database. Non mi interessa se i conteggi scompaiono dopo il riavvio del server. Ma finché il server è attivo, voglio che questi conteggi siano coerenti tra la shell di Django e l'interfaccia web, e voglio essere in grado di restituire quante volte l'azione ha avuto luogo su ogni istanza di modello.Python Django Global Variables

Non voglio che le variabili siano associate a un utente o una sessione perché potrei voler restituire questi conteggi senza essere loggato (e voglio che i conteggi siano coerenti indipendentemente da quale utente abbia effettuato l'accesso). Sto descrivendo una variabile globale? Se è così, come posso usarne uno in Django? Ho notato che i file come urls.py, settings.py e models.py sembrano essere analizzati solo una volta per l'avvio del server (al contrario di views.py, che sembra essere analizzato a quando viene fatta una richiesta). Questo significa che dovrei dichiarare le mie variabili in uno di questi file? O dovrei archiviarlo in un attributo di modello in qualche modo (purché rimanga fermo fino a quando il server è in esecuzione)? Questa è probabilmente una domanda facile, ma non sono sicuro di come è stato fatto in Django.

Qualsiasi commento o consiglio è molto apprezzato. Grazie, Joe

+0

I documenti di memorizzazione nella cache sono un po '"caching-a-page" centrico. Passare a "basso livello" per i dettagli sul suo utilizzo per le variabili del server: https://docs.djangoproject.com/en/1.3/topics/cache/#the-low-level-cache-api –

+0

Questo potrebbe aiutarti a: [https://github.com/andres-torres-marroquin/django-system-globals](https://github.com/andres-torres-marroquin/django-system-globals) –

risposta

24

È non devono dichiarare le variabili globali. Le impostazioni (costanti) sono OK se fatte bene. Ma le variabili violano con l'architettura condivisa-nulla e potrebbero causare un sacco di problemi. (il caso migliore sarà incoerente)

Vorrei semplicemente memorizzare quelle statistiche nella cache. (Beh, in realtà avrei memorizzarli nel database e si chiarito si credere che avrà un impatto negativo sulle prestazioni, quindi ...)

I nuovi incr() e decr() metodi sono particolarmente adatti per il conteggio. Vedi docs per maggiori informazioni.

+3

+1 per la memorizzazione di questi in il cache. –

+0

Mi piace questo approccio e lo sto implementando.Attualmente sto usando localmem per il backend cache sul server di sviluppo Django e ho notato che i conteggi non persistono dopo aver sfogliato diverse pagine web nel mio sito. (In quel momento NON riavvii il server di sviluppo di django) Mi rendo conto che potrebbero esserci molteplici ragioni per questo. (Alla fine userò memcached). Mi chiedo solo se il server di sviluppo cache/django localmem non trattiene i valori memorizzati nella cache a lungo o se in qualche modo ho sbagliato l'impostazione della configurazione. –

+0

@Joe: utilizzo sempre la cache di db in assenza di un backend di cache adeguato come memcached. Giusto per essere sicuro. Ciò va di pari passo con "non preoccuparsi affatto dei problemi di prestazioni finché non sono evidenti" e "misurare prima di ottimizzare". – muhuk

54

Perché uno non deve dichiarare variabili globali? O_o. Sembra solo una propaganda. Se l'autore sa cosa vuole e quali effetti collaterali saranno, perché no. Forse è solo un rapido esperimento.

È possibile dichiarare il contatore come modello classe -membro. Quindi per gestire le condizioni di gara devi aggiungere un metodo che attenderà se qualche altro client, da un altro thread, funziona con il contatore. Qualcosa di simile a questo:

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 

Ricorda però: bisogna avere la vostra applicazione in un unico processo di . Quindi, se hai distribuito l'applicazione sotto Apache, assicurati che sia configurato per generare molti thread, ma non molti processi. Se stai sperimentando con ./manage.py run non sono richieste azioni.

+1

Questo è esattamente quello che voglio. Devo generare un ID seriale che dovrebbe essere incrementato per ogni richiesta a scopo di test. Nel sistema attuale, l'ID proviene da API esterne. – k4ml

+2

Questo potrebbe essere un approccio praticabile per i progetti di giocattoli. Ma una volta che inizi a utilizzare questo corso, hai garantito che la tua applicazione non è scalabile. C'è un motivo per cui abbiamo il sottosistema della cache. – muhuk

+1

ho usato questo approccio per istanziare una volta un client per un servizio macchina, istanziarlo ogni volta rallenta il mio server web ... – thrantir