2010-10-28 11 views
14

Voglio avere delle costanti in un progetto Django. Ad esempio, diciamo una costante denominata MIN_TIME_TEST.Definizione di costanti in Django

Mi piacerebbe poter accedere a questa costante in due punti: dal mio codice Python e da qualsiasi modello.

Qual è il modo migliore per farlo?

EDIT: Per chiarire, so di modelli processori Contesto e circa appena mettere le cose in settings.py o qualche altro file e solo l'importazione.

La mia domanda è, come posso combinare i due approcci senza violare la regola "Non ripetere te stesso"? Sulla base delle risposte finora, ecco il mio approccio:

Vorrei creare un file chiamato global_constants.py, che avrà un elenco di costanti (cose come MIN_TIME_TEST = 5). Posso import questo file in qualsiasi modulo per ottenere le costanti.

Ma ora, voglio creare il processore di contesto che restituisce tutte queste costanti. Come posso fare questo automaticamente, senza doverli elencare di nuovo in un dizionario, come nella risposta di John Mee?

risposta

14

Sia Luper sia Vladimir sono imho corretti ma avrete bisogno di entrambi per completare le vostre esigenze.

  • Anche se, le costanti non hanno bisogno di essere nel settings.py, si potrebbe mettere ovunque e importarli da quel luogo nel codice/modello/modulo di vista. A volte li metto nello __init__.py se non mi interessa che siano considerati rilevanti a livello globale.

  • un processore contesto come questo farà sì che le variabili selezionate sono globalmente nel modello portata

    def settings(request): 
        """ 
        Put selected settings variables into the default template context 
        """ 
        from django.conf import settings 
        return { 
         'DOMAIN':  settings.DOMAIN, 
         'GOOGLEMAPS_API_KEY': settings.GOOGLEMAPS_API_KEY, 
        } 
    

Ma questo potrebbe essere eccessivo se siete nuovi a Django; forse stai solo chiedendo come inserire le variabili nello scope template ...?

from django.conf import settings 

... 
# do stuff with settings.MIN_TIME_TEST as you wish 

render_to_response("the_template.html", { 
    "MIN_TIME_TEST": settings.MIN_TIME_TEST 
}, context_instance=RequestContext(request) 
+0

Grazie, è davvero la direzione che voglio andare. Ma per favore vedi il mio chiarimento/altra domanda, ad esempio, come posso fare ciò che dici senza dover elencare tutte le costanti due volte? –

+0

Avvolgili tutti in un dizionario quindi inserisci il dizionario nel contesto. Li accederai tramite notazione dot. es .: {{yourDict.yourConstant}} –

3

Considera di inserirlo in settings.py della tua applicazione. Ovviamente, per poterlo utilizzare nel template, sarà necessario renderlo disponibile al template come qualsiasi altra variabile usuale.

2

Utilizzare context processors per avere le costanti disponibili in tutti i modelli (settings.py è un bel posto per definirli come detto da Vladimir).

+0

Che cosa è un buon modo di aggiungendoli nei processori di contesto dopo definendoli in settings.py? Preferirei non dover ripetere più volte i nomi di tutte le costanti. –

+0

Tutte le informazioni sono disponibili sulla pagina Luper Rouch linkato. Dovrai creare una funzione python che restituirà un dizionario di vars (che è dove restituisci le costanti) ed elenca la tua funzione nell'impostazione TEMPLATE_CONTEXT_PROCESSORS. –

0

Nel processore contesto si può usare qualcosa di simile a:

import settings 

context = {} 
for item in dir(settings): 
    #use some way to exclude __doc__, __name__, etc.. 
    if item[0:2] != '__': 
     context[item] = getattr(settings, item) 
4

Per costruire sulle risposte degli altri, ecco un modo semplice che ci si implementa questo:

Nel file impostazioni:

GLOBAL_SETTINGS = { 
    'MIN_TIME_TEST': 'blah', 
    'RANDOM_GLOBAL_VAR': 'blah', 
} 

Poi, la costruzione di fuori di John Mee's context processor:

def settings(request): 
    """ 
    Put selected settings variables into the default template context 
    """ 
    from django.conf import settings 
    return settings.GLOBAL_SETTINGS 

Questo risolverà il problema di DRY.

O, se solo si prevede di utilizzare le impostazioni globali di tanto in tanto e vogliono chiamarli dalla visualizzazione:

def view_func(request): 
    from django.conf import settings 
    # function code here 
    ctx = {} #context variables here 
    ctx.update(settings.GLOBAL_SETTINGS) 
    # whatever output you want here 
0

variante ultima parte di John Mee, con un po 'di elaborazione sulla stessa idea Giordano Reiter discute.

Supponiamo di avere qualcosa nelle impostazioni simile a quello che Jordan ha suggerito - in altre parole, qualcosa di simile a:

GLOBAL_SETTINGS = { 
    'SOME_CONST': 'thingy', 
    'SOME_OTHER_CONST': 'other_thingy', 
} 

Supponiamo inoltre si dispone già di un dizionario con alcune delle variabili che desideri passare il tuo modello, forse passato come argomento alla tua vista. Chiamiamolo my_dict. Supponiamo di volere che i valori in my_dict sostituiscano quelli del dizionario settings.GLOBAL_SETTINGS.

Si potrebbe fare qualcosa nella vista come:

def my_view(request, *args, **kwargs) 
    from django.conf import settings 
    my_dict = some_kind_of_arg_parsing(*args,**kwargs) 
    tmp = settings.GLOBAL_SETTINGS.copy() 
    tmp.update(my_dict) 
    my_dict = tmp 
    render_to_response('the_template.html', my_dict, context_instance=RequestContext(request)) 

Questo ti permette di avere le impostazioni determinate a livello globale, a disposizione i modelli, e non richiede di digitare manualmente ciascuno di essi.

Se non ha qualunque variabili aggiuntive per passare il modello, né alcuna necessità di sovrascrivere, si può solo fare:

render_to_response('the_template.html', settings.GLOBAL_SETTINGS, context_instance=RequestContext(request)) 

La principale differenza tra quello che sto discutendo qui & cosa Jordan ha, è quello per il suo, settings.GLOBAL_SETTINGS sovrascrive tutto ciò che può avere in comune w/il tuo dizionario di contesto, e con il mio, il mio dizionario di contesto sovrascrive settings.GLOBAL_SETTINGS. YMMV.

1

I processori di contesto sono più adatti alla gestione di dati di oggetti più dinamici: sono definiti come una mappatura nello documentation e in molti dei post qui vengono modificati o passati alle viste - non lo fa ha senso che un modello possa perdere l'accesso alle informazioni globali perché, ad esempio, si è dimenticato di utilizzare un processore di contesto specializzato nella vista. I dati sono globali per definizione & che accoppia la vista al modello.

Un modo migliore è definire un tag modello personalizzato.In questo modo:

  • modelli non si affidano a vista di avere informazioni globali passato nelle loro
  • è asciutto-er: l'applicazione che definisce le impostazioni globali possono essere esportati in molti progetti, eliminando codice comune tra i progetti
  • modelli di decidere se hanno accesso alle informazioni a livello mondiale, non le funzioni di visualizzazione

nell'esempio qui sotto ho a che fare con il tuo problema - di carico in questo MIN_TIME_TEST variabili - e un problema che comunemente faccia, carico in URL che cambiano quando il mio ambiente c HANGES.

Ho 4 ambienti - 2 dev e 2 produzione:

  • Dev: Django server Web, url: localhost: 8000
  • Dev: web server Apache: url: sandbox.com -> delibera di 127.0.0.1
  • server di sandbox Prod, url: sandbox.domain.com
  • Prod server: url: domain.com

Lo faccio in tutti i miei progetti & conserva tutti gli URL in un file, global_settings.py in modo che sia accessibile dal codice. Definisco un tag modello personalizzato {% site_url%} che può essere (facoltativamente) caricato in qualsiasi modello

Creo un'app chiamata global_settings e assicurati che sia inclusa nelle mie impostazioni.INSTALLED_APPS tupla.

Django compila il testo su modelli in nodi con un metodo render(), che spiega come devono essere visualizzati i dati -. Ho creato un oggetto che rende i dati da returnning valori nel mio global_settings.py in base al nome passato in

Ecco come si presenta:

from django import template 
import global_settings 

class GlobalSettingNode(template.Node): 
    def __init__(self, settingname): 
     self.settingname = settingname; 
    def render(self, context): 
     if hasattr(global_settings, self.settingname): 
      return getattr(global_settings, self.settingname) 
     else: 
      raise template.TemplateSyntaxError('%s tag does not exist' % self.settingname) 

Ora, in global_settings.py registro un paio di tag: site_url per il mio esempio e min_test_time per il vostro esempio. In questo modo, quando {% min_time_test%} viene richiamato da un modello, chiamerà get_min_time_test che risolve il caricamento nel valore = 5. Nel mio esempio, {% site_url%} eseguirà una ricerca basata sul nome in modo da poter mantenere tutti e 4 gli URL definiti contemporaneamente e scegliere l'ambiente che sto utilizzando. Questo per me è più flessibile del semplice utilizzo delle impostazioni integrate di Django.Debug = True/False flag.

from django import template 
from templatenodes import GlobalSettingNode 
register = template.Library() 


MIN_TIME_TEST = 5 

DEV_DJANGO_SITE_URL = 'http://localhost:8000/' 
DEV_APACHE_SITE_URL = 'http://sandbox.com/' 
PROD_SANDBOX_URL = 'http://sandbox.domain.com/' 
PROD_URL = 'http://domain.com/' 

CURRENT_ENVIRONMENT = 'DEV_DJANGO_SITE_URL' 



def get_site_url(parser, token): 
    return GlobalSettingNode(CURRENT_ENVIRONMENT) 

def get_min_time_test(parser, token): 
    return GlobalSettingNode('MIN_TIME_TEST') 

register.tag('site_url', get_site_url) 
register.tag('min_time_test', get_min_time_test) 

Si noti che per questo lavoro, Django si aspetta global_settings.py per essere collocata in un pitone confezionato chiamato templatetags sotto il Django app. Il mio Django applicazione qui si chiama global_settings, quindi la mia struttura di directory si presenta come:

/project-name/global_settings/templatetags/global_settings.py ecc

Infine il modello sceglie se caricare nelle impostazioni globali o no , che è vantaggioso per le prestazioni. Aggiungi questa linea al tuo modello per esporre tutti i tag registrati in global_settings.py:

{% load global_settings %} 

Ora, altri progetti che hanno bisogno MIN_TIME_TEST o questi ambienti esposti può semplicemente installare questa app =)