Come si aggiungono più argomenti al filtro del mio modello personalizzato in un modello django?


89

Ecco il mio filtro personalizzato:

from django import template

register = template.Library()

@register.filter
def replace(value, cherche, remplacement):
    return value.replace(cherche, remplacement)

ed ecco i modi in cui ho provato a utilizzarlo nel mio file modello che ha generato un errore:

{{ attr.name|replace:"_"," " }}
{{ attr.name|replace:"_" " " }}
{{ attr.name|replace:"_":" " }}
{{ attr.name|replace:"cherche='_', remplacement=' '" }}

Ho esaminato i documenti e il libro di django ma ho trovato solo esempi utilizzando un singolo argomento ... è anche possibile?

Risposte:


108

È possibile e abbastanza semplice.

Django consente solo un argomento al tuo filtro, ma non c'è motivo per cui non puoi mettere tutti i tuoi argomenti in una singola stringa usando una virgola per separarli.

Quindi, ad esempio, se desideri un filtro che controlli se la variabile X è nell'elenco [1,2,3,4], vorrai un filtro modello simile a questo:

{% if X|is_in:"1,2,3,4" %}

Ora possiamo creare il tuo templatetag in questo modo:

from django.template import Library

register = Library()

def is_in(var, args):
    if args is None:
        return False
    arg_list = [arg.strip() for arg in args.split(',')]
    return var in arg_list

register.filter(is_in)

La riga che crea arg_list è un'espressione generatore che divide la stringa args su tutte le virgole e chiama .strip () per rimuovere eventuali spazi iniziali e finali.

Se, ad esempio, il terzo argomento è un int, basta fare:

arg_list[2] = int(arg_list[2])

O se tutti sono int:

arg_list = [int(arg) for arg in args.split(',')]

MODIFICA: ora per rispondere in modo specifico alla tua domanda utilizzando coppie chiave e valore come parametri, puoi utilizzare la stessa classe che Django usa per analizzare le stringhe di query dagli URL, che quindi ha anche il vantaggio di gestire correttamente la codifica dei caratteri in base alle tue impostazioni.py .

Quindi, come con le stringhe di query, ogni parametro è separato da "&":

{{ attr.name|replace:"cherche=_&remplacement= " }}

Quindi la tua funzione di sostituzione ora sarà simile a questa:

from django import template
from django.http import QueryDict

register = template.Library()

@register.filter
def replace(value, args):
    qs = QueryDict(args)
    if qs.has_key('cherche') and qs.has_key('remplacement'):
        return value.replace(qs['cherche'], qs['remplacement'])
    else:
        return value

Potresti velocizzarne alcuni a rischio di fare alcune sostituzioni errate:

qs = QueryDict(args)
return value.replace(qs.get('cherche',''), qs.get('remplacement',''))

1
Se i valori per questi sono in variabili come implementare questo ...?
Anto

2
Sembrava utile, ma non sono riuscito a farlo funzionare con le variabili passate. Per fare ciò, ho dovuto usare un tago simple_tag- che consente di passare più variabili, anche variabili con nome.
Furbeenator

18

Non possibile secondo questa sezione dei documenti:

I filtri personalizzati sono solo funzioni Python che accettano uno o due argomenti:

  • Il valore della variabile (input) - non necessariamente una stringa.
  • Il valore dell'argomento: questo può avere un valore predefinito o essere tralasciato del tutto.

L'approccio di Van Gale funzionerà se utilizzi stringhe hard-coded. Il ticket Django [ code.djangoproject.com/ticket/1199] supporta più argomenti in un filtro personalizzato ed è stata accettata una patch.
Jeff Bauer

17

È facile così.

@register.filter(name='one_more')
def one_more(_1, _2):
    return _1, _2

def your_filter(_1_2, _3)
    _1, _2 = _1_2
    print "now you have three arguments, enjoy"

{{ _1|one_more:_2|your_filter:_3 }}

Davvero un grande grazie per questa soluzione. L'ho aggiornato un po 'in modo da poter concatenare diverse lunghezze di parametri. gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
Filip Dobrovolný

1
Questa dovrebbe essere la risposta corretta! È una bellissima soluzione python (forse non la migliore soluzione django, vedi la risposta di @dragonroot)
Antoine Draune

15

Invece di un filtro, registra il tuo tag come un semplice tag. Questi possono richiedere più argomenti. La sintassi per invocarlo sarà leggermente diversa, ma è solo un cambiamento sintattico dello zucchero.


2
Questa era la risposta corretta per il mio problema. Per passare una variabile modello in questa funzione, ho dovuto utilizzare un file simple_tag.
Furbeenator

1
Questa è una buona soluzione. Vale sicuramente la pena controllare i documenti di django per il semplice tag: docs.djangoproject.com/en/1.8/howto/custom-template-tags/…
Gunther

6

È più semplice di quanto pensi

Puoi usare simple_tag per questo.

@register.simple_tag
def multiple_args_tag(a, b, c, d):
   #do your stuff
   return 

Nel modello :

{% multiple_args_tag 'arg1' 'arg2' 'arg3' 'arg4' %}

NOTA: non dimenticare di rieseguire il server.


4

Questa funzione è stata contrassegnata come WONTFIX nel 2013 Django's Trac: http://code.djangoproject.com/ticket/1199


Quel ticket è stato chiuso come WONTFIX l'anno scorso (2013), il loro sviluppatore suggerisce di utilizzare un tag personalizzato se sono necessari più argomenti.
Paul Lo

3

<my-site> /globaltags/replace.py

from django.template import Library

import re

register = Library()

def search(value, search):
    return re.sub(search, '#f4x@SgXXmS', value)

def replace(value, replace):
    return re.sub('#f4x@SgXXmS', replace, value)

register.filter(search)
register.filter(replace)

Nel modello:

{{ "saniel"|search:"s"|replace:"d" }}

Sarebbe bello se mi spiegassi #f4x@SgXXmSqualcosa?
Dan Abramov

1
solo una stringa casuale usata come segnaposto. Ho scelto questa stringa perché credevo che non facesse parte della stringa di input. Se per esempio ho usato "{}" invece di "# f4x @ SgXXmS" {{"use {} invece off []" | search: "off" | replace: "of"}} restituirebbe: "use of invece di [] "e non il risultato atteso:" usa {} invece di [] "
theosp

5
Oh, ha senso. Potrebbe essere carino dichiararlo come SUBSTRING_THAT_NEVER_OCCURSpensiero.
Dan Abramov

-1

Puoi semplicemente fare questo:

{% assign find_total_issued = dailysalesreport | find: "TotalIssued":"13" %}

public static List<object> Find(object collection, string column, string value)

E raggiungerà la destinazione come è l'astrazione della funzione sjare.


-2

Ecco una cattiva idea ma funziona:

{{ xml|input_by_xpath:"{'type':'radio','xpath':'//result/value'}" }}

e

@register.filter
def input_by_xpath(device, args): 
    args = eval(args)
    ...
    result = "<input type=\"%s\" value=\"%s\" name=\"%s\"/>"%(args['type'],value,args['xpath'])
    return mark_safe(result)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.