2009-09-29 16 views
14

Ho un filtro currency, che assume un valore in USD e lo converte in una valuta (o USD o GBP). La valuta da convertire è memorizzata nella sessione, ma i filtri non prendono RequestContext, quindi non posso prenderlo direttamente da lì.Django - l'accesso alla RequestContext dall'interno di un filtro personalizzato

C'è un modo migliore di passare l'elemento sessione di rilevante nel modello, e dal modello nel filtro come argomento? Mentre questo approccio funziona, sembra abbastanza orribile, e probabilmente finirò per passare la valuta a (quasi) ogni modello.

mio filtro attualmente simile a questa:

def currency(value, currency): 
    if currency == 'usd': 
     val = '$%.2f' % value 
     return mark_safe(val) 

    d = Decimal(value) 
    val = '£%.2f' % (d*Decimal('0.63')) 

    return mark_safe(val) 

risposta

7

Se si crea un tag modello invece di un filtro, si è data contesto di lavorare con (che contiene la richiesta). http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#writing-custom-template-tags

+1

@Adam - forse sono di spessore, ma non riesco a vedere in questi documenti come ottenere l'accesso alle variabili di sessione dai tag dei modelli personalizzati. Potresti darmi un esempio o far notare cosa mi manca? –

+1

Ah - scavare attorno ad esso sembra essere passato come primo argomento del tag (appena trovato un esempio che aggiunge una classe ai link che corrispondono a un'espressione regolare, che sembra (a) utile e (b) adattabile - http: // gnuvince .wordpress.com/2007/09/14/un-django-template-tag-per-il-corrente-attiva-page /). –

+0

A destra, il contesto è un parametro standard del metodo di rendering sul nodo del tag di modello. Se hai bisogno di un ulteriore esempio specifico, sono sicuro che potrei raccoglierne uno. – Adam

3

Questo può essere fatto utilizzando un filtro. Innanzitutto assicurati di avere "django.core.context_processors.request" in te TEMPLATE_CONTEXT_PROCESSORS. Se non lo fai, è possibile aggiungere questo al file settings.py:

TEMPLATE_CONTEXT_PROCESSORS += (
    "django.core.context_processors.request" 
) 

Poi nel modello, il filtro sarà simile a questa (supponendo che il variabile di sessione è denominato 'currency_type'):

{{value|currency:request.session.currency_type}} 

Oppure è qualcosa di simile a quello che stai considerando abbastanza orribile?

+0

Lui è; Guarda cosa sta facendo, quel filtro descrive esattamente quello che stai dicendo. – fijter

+0

Ho pensato che potrebbe lamentarsi del processo di dover passare esplicitamente la variabile attraverso la vista. Questo lo renderà disponibile automaticamente. Posso anche pubblicare un esempio di utilizzo di un tag modello con takes_context = True nel decoratore – Zach

3

Sarei d'accordo con Adam che la migrazione del codice a un tag personalizzato sia il modo migliore.

Tuttavia, un cliente aveva bisogno di registrare l'uso di alcuni filtri solo quando una pagina è stata pubblicata e aveva un enorme inventario di modelli che utilizzare la sintassi filtro esistente. Sarebbe stato un impegno costoso riscrivere tutti i modelli. Quindi, mi si avvicinò con questa semplice funzione che estrae il contesto dalla chiamata stack:

https://gist.github.com/drhoden/e05292e52fd5fc92cc3b

def get_context(max_depth=4): 
    import inspect 
    stack = inspect.stack()[2:max_depth] 
    context = {} 
    for frame_info in stack: 
     frame = frame_info[0] 
     arg_info = inspect.getargvalues(frame) 
     if 'context' in arg_info.locals: 
      context = arg_info.locals['context'] 
      break 
    return context 

Leggere attentamente i miei avvertimenti, ma questo dà l'accesso filtri standard per il contesto (quando è disponibile) SENZA dover trasformare il filtro in un tag.

+1

È fantastico, non sono sicuro se fantastico in modo buono o cattivo, ma fantastico;) –

0

Una soluzione hacky in qualche modo meno la proposta di Daniel Rhoden è, per usare threading.local(). Definisci una classe middleware, che memorizza il tuo request come oggetto globale all'interno del thread locale e aggiungi tale classe al tuo MIDDLEWARE_CLASSES.

Ora un filtro modello può accedere facilmente a quell'oggetto richiesta.

Problemi correlati