Como posso adicionar vários argumentos para o meu filtro de modelo personalizado em um modelo de Django?

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

  •  05-07-2019
  •  | 
  •  

Pergunta

Aqui está o meu filtro personalizado:

from django import template

register = template.Library()

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

e aqui estão as maneiras que eu tentei usá-lo no meu arquivo de modelo que resultaram em um erro:

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

Eu olhei para do Django docs e livro mas apenas exemplo encontrado usando um único argumento ... é mesmo possível?

Foi útil?

Solução

É possível e bastante simples.

Django permite apenas um argumento para o filtro, mas não há nenhuma razão você não pode colocar todos os seus argumentos em uma única string usando uma vírgula para separá-los.

Assim, por exemplo, se você quiser um filtro que verifica se a variável X está na lista [1,2,3,4] você vai querer um filtro modelo que se parece com isso:

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

Agora podemos criar a sua templatetag assim:

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)

A linha que cria arg_list é um gerador de expressão que divide a seqüência de argumentos sobre todas as vírgulas e chamadas .strip () para remover qualquer esquerda e à direita espaços.

Se, por exemplo, o terceiro argumento é um int em seguida, basta fazer:

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

Ou se todos eles são ints fazer:

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

EDIT: agora especificamente responder a sua pergunta usando a chave, pares de valores como parâmetros, você pode usar a mesma classe usos Django para seqüências de consulta de análise de URL, que então também tem a vantagem de lidar com codificação de caracteres corretamente de acordo com o seu settings.py.

Assim, como com seqüências de consulta, cada parâmetro é separado por '&':

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

Em seguida, seu substituir a função vai ficar assim:

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

Você pode acelerar este processo alguns correndo o risco de fazer algumas substituições incorretas:

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

Outras dicas

Não possível de acordo com a Nesta seção dos docs:

Os filtros personalizados são apenas funções Python que levam um ou dois argumentos:

  • O valor da variável (entrada) - não necessariamente uma string.
  • O valor do argumento - isso pode ter um valor padrão, ou ser deixado de fora.

Em vez de um filtro, inscreva a sua etiqueta como uma etiqueta simples. Aqueles pode levar vários argumentos. A sintaxe para invocar que vai ser um pouco diferente, mas isso é apenas sintática açúcar mudando.

É fácil assim.

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

Este recurso foi marcada como WONTFIX em 2013 Trac do Django: http://code.djangoproject.com / ingressos / 1199

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

No modelo:

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

Você pode simplesmente fazer isso:

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

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

E vai chegar ao destino, como a abstração da função é sjare.

Aqui está uma má idéia, mas funciona:

{{ 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)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top