Comment ajouter plusieurs arguments à mon filtre de modèle personnalisé dans un modèle Django?

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

  •  05-07-2019
  •  | 
  •  

Question

Voici mon filtre personnalisé:

from django import template

register = template.Library()

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

et voici comment j'ai essayé de l'utiliser dans mon fichier de modèle, ce qui a entraîné une erreur:

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

J'ai examiné les la documentation de django et book , mais uniquement un exemple utilisant un seul argument ... est-ce possible?

Était-ce utile?

La solution

C'est possible et assez simple.

Django n'autorise qu'un seul argument à votre filtre, mais rien n'empêche de placer tous vos arguments dans une seule chaîne en les séparant par une virgule.

Ainsi, par exemple, si vous souhaitez un filtre qui vérifie si la variable X est dans la liste [1,2,3,4], vous souhaiterez un filtre de modèle ressemblant à ceci:

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

Nous pouvons maintenant créer votre étiquette de modèle comme ceci:

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 ligne qui crée arg_list est une expression génératrice qui divise la chaîne args de toutes les virgules et appelle .strip () pour supprimer les espaces de début et de fin.

Si, par exemple, le 3ème argument est un int, il suffit de faire:

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

Ou si tous les utilisateurs sont concernés:

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

EDIT: pour répondre spécifiquement à votre question en utilisant des paires clé / valeur, vous pouvez utiliser la même classe que celle utilisée par Django pour analyser les chaînes de requête hors de l'URL, ce qui présente également l'avantage de gérer correctement le codage des caractères en fonction de vos besoins. settings.py.

Donc, comme pour les chaînes de requête, chaque paramètre est séparé par '& amp;':

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

Ensuite, votre fonction de remplacement ressemblera à ceci:

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

Vous pourriez accélérer le processus au risque de procéder à des remplacements incorrects:

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

Autres conseils

Impossible selon cette section de la documentation:

Les filtres personnalisés ne sont que des fonctions Python qui prennent un ou deux arguments:

  • La valeur de la variable (entrée) - pas nécessairement une chaîne.
  • La valeur de l'argument - cela peut avoir un valeur par défaut, ou être totalement omis.

Au lieu d’un filtre, enregistrez votre tag en tant que tag simple. Ceux-ci peuvent prendre plusieurs arguments. La syntaxe pour l'invoquer sera un peu différente, mais ce n'est que du sucre syntaxique qui change.

C'est simple comme ça.

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

Cette fonctionnalité a été marquée comme WONTFIX en 2013 Le Trac de Django: http://code.djangoproject.com / ticket / 1199

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

Dans le modèle:

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

Vous pouvez simplement faire ceci:

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

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

Et il atteindra la destination car l'abstraction de la fonction est sjare.

Voici une mauvaise idée mais fonctionne:

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

et

@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)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top