¿Cómo agrego múltiples argumentos a mi filtro de plantilla personalizado en una plantilla de django?

StackOverflow https://stackoverflow.com/questions/420703

  •  05-07-2019
  •  | 
  •  

Pregunta

Aquí está mi filtro personalizado:

from django import template

register = template.Library()

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

y aquí están las formas en que intenté usarlo en mi archivo de plantilla que resultó en un error:

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

Miré en documentos de django y book pero solo encontré un ejemplo usando un solo argumento ... ¿es posible?

¿Fue útil?

Solución

Es posible y bastante simple.

Django solo permite un argumento para su filtro, pero no hay razón para que no pueda poner todos sus argumentos en una sola cadena usando una coma para separarlos.

Entonces, por ejemplo, si desea un filtro que verifique si la variable X está en la lista [1,2,3,4], querrá un filtro de plantilla que se vea así:

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

Ahora podemos crear su etiqueta de plantilla de esta manera:

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 línea que crea arg_list es una expresión generadora que divide la cadena de argumentos en todas las comas y llama a .strip () para eliminar los espacios iniciales y finales.

Si, por ejemplo, el tercer argumento es un int, simplemente hazlo:

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

O si todos son ints, haga lo siguiente:

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

EDITAR: ahora para responder específicamente a su pregunta mediante el uso de pares de clave y valor como parámetros, puede usar la misma clase que Django usa para analizar las cadenas de consulta de las URL, lo que también tiene la ventaja de manejar la codificación de caracteres correctamente de acuerdo con su settings.py.

Entonces, como con las cadenas de consulta, cada parámetro está separado por '& amp;':

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

Entonces su función de reemplazo ahora se verá así:

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

Puede acelerar esto a riesgo de hacer algunos reemplazos incorrectos:

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

Otros consejos

No es posible según esta sección de los documentos:

Los filtros personalizados son solo funciones de Python que toman uno o dos argumentos:

  • El valor de la variable (entrada) - No necesariamente una cadena.
  • El valor del argumento: esto puede tener un valor predeterminado, o quedar fuera por completo.

En lugar de un filtro, registre su etiqueta como una etiqueta simple. Esos pueden tomar múltiples argumentos. La sintaxis para invocarlo será un poco diferente, pero eso es solo un cambio de azúcar sintáctico.

Es así de fácil.

@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 }}

Esta función se marcó como WONTFIX en 2013 Django's Trac: http://code.djangoproject.com / ticket / 1199

<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)

En la plantilla:

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

Puede simplemente hacer esto:

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

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

Y llegará al destino ya que la abstracción de la función es sjare.

Heres una mala idea pero funciona:

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

y

@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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top