web-dev-qa-db-fra.com

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

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 les façons dont j'ai essayé de l'utiliser dans mon fichier de modèle qui a entraîné une erreur:

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

J'ai examiné les documents de Django et book mais je n'ai trouvé d'exemple qu'en utilisant un seul argument ... est-ce même possible?

79
bchhun

C'est possible et assez simple.

Django n'autorise qu'un seul argument dans votre filtre, mais il n'y a aucune raison pour que vous ne puissiez pas mettre tous vos arguments dans une seule chaîne en utilisant une virgule pour les séparer.

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

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

Maintenant, nous pouvons créer votre 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 de générateur qui fractionne la chaîne args sur 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 entier, faites simplement:

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

Ou si tous sont des pouces, faites:

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

EDIT: maintenant pour répondre spécifiquement à votre question en utilisant des paires clé/valeur comme paramètres, vous pouvez utiliser la même classe Django utilise pour analyser les chaînes de requête des URL, ce qui a également l'avantage de gérer l'encodage des caractères correctement en fonction de votre settings.py.

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

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

Votre fonction de remplacement ressemblera alors à 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 pouvez accélérer cela au risque de faire des remplacements incorrects:

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

Pas possible selon cette section des documents:

Les filtres personnalisés ne sont que des fonctions Python qui acceptent 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 une valeur par défaut, ou être laissé de côté.
17
Jeff Bauer

C'est facile 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 }}
10
gshmu

Au lieu d'un filtre, enregistrez votre balise comme une simple balise. Ceux-ci peuvent prendre plusieurs arguments. La syntaxe pour l'invoquer sera un peu différente, mais ce n'est qu'un changement de sucre syntaxique.

10
dragonroot

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

4
bchhun

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

Dans le modèle:

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