Как добавить несколько аргументов к моему настраиваемому фильтру шаблона в шаблоне django?

89

Вот мой собственный фильтр:

from django import template

register = template.Library()

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

и вот способы, которыми я пытался использовать его в своем файле шаблона, что привело к ошибке:

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

Я просмотрел документы и книгу django, но нашел только пример с одним аргументом ... возможно ли это?

bchhun
источник

Ответы:

108

Это возможно и довольно просто.

Django допускает только один аргумент для вашего фильтра, но нет причин, по которым вы не можете поместить все свои аргументы в одну строку, используя запятую для их разделения.

Так, например, если вам нужен фильтр, который проверяет, находится ли переменная X в списке [1,2,3,4], вам понадобится шаблонный фильтр, который выглядит следующим образом:

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

Теперь мы можем создать ваш шаблонный тег следующим образом:

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)

Строка, которая создает arg_list, является выражением генератора, которое разбивает строку args на все запятые и вызывает .strip () для удаления начальных и конечных пробелов.

Если, например, третий аргумент - это int, просто выполните:

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

Или, если все они целые, сделайте:

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

РЕДАКТИРОВАТЬ: теперь, чтобы конкретно ответить на ваш вопрос, используя пары ключ, значение в качестве параметров, вы можете использовать тот же класс, который Django использует для синтаксического анализа строк запроса из URL-адресов, который также имеет преимущество правильной обработки кодировки символов в соответствии с вашими settings.py .

Итак, как и в случае со строками запроса, каждый параметр разделяется символом '&':

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

Тогда ваша функция замены теперь будет выглядеть так:

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

Вы можете немного ускорить это, рискуя выполнить некорректную замену:

qs = QueryDict(args)
return value.replace(qs.get('cherche',''), qs.get('remplacement',''))
Ван Гейл
источник
1
Если значения для них находятся в переменных, как это реализовать ...?
Anto
2
Это казалось полезным, но я не мог заставить его работать с передаваемыми переменными. Для этого я использовал tagили simple_tag-, который позволяет передавать несколько переменных, даже именованные переменные.
Furbeenator
18

Невозможно в соответствии с этим разделом документов:

Пользовательские фильтры - это просто функции Python, которые принимают один или два аргумента:

  • Значение переменной (вход) - не обязательно строка.
  • Значение аргумента - может иметь значение по умолчанию или вообще не учитываться.
Джефф Бауэр
источник
Подход Ван Гейла будет работать, если вы используете жестко запрограммированные строки. Билет Django [ code.djangoproject.com/ticket/1199] поддерживает несколько аргументов в настраиваемом фильтре, и исправление было принято.
Джефф Бауэр
17

Это просто.

@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 }}
гшму
источник
Действительно большое спасибо за это решение. Я немного модернизировал его, чтобы вы могли связывать параметры разной длины. gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
Филип Добровольный
1
Это должен быть правильный ответ! Это красивое решение для Python (возможно, не лучшее решение для django, см. Ответ @dragonroot)
Антуан Драун
15

Вместо фильтра зарегистрируйте свой тег как простой тег. Они могут принимать несколько аргументов. Синтаксис для его вызова будет немного другим, но это просто синтаксическое изменение сахара.

корень дракона
источник
2
Это был правильный ответ на мою проблему. Чтобы передать переменную шаблона в эту функцию, мне пришлось использовать файл simple_tag.
Furbeenator
1
Это хорошее решение. Определенно стоит проверить документацию django на предмет простого тега: docs.djangoproject.com/en/1.8/howto/custom-template-tags/…
Гюнтер
6

Это проще, чем вы думаете. Для этого

можно использовать simple_tag .

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

В шаблоне :

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

ПРИМЕЧАНИЕ. Не забудьте перезапустить сервер.

Саван Чаухан
источник
4

Эта функция была отмечена как WONTFIX в Django Trac 2013 года: http://code.djangoproject.com/ticket/1199

bchhun
источник
Этот билет был закрыт как WONTFIX в прошлом году (2013), их разработчик предлагает использовать настраиваемый тег, если требуется несколько аргументов.
Пол Ло
3

<мой-сайт> /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)

В шаблоне:

{{ "saniel"|search:"s"|replace:"d" }}
теосп
источник
Было бы неплохо, если бы вы #f4x@SgXXmSнемного объяснили ?
Дэн Абрамов
1
просто случайная строка, используемая в качестве заполнителя. Я выбрал эту строку, потому что полагал, что она не будет частью входной строки. Если, например, я использовал "{}" вместо '# f4x @ SgXXmS' {{"использовать {} вместо off []" | search: "off" | replace: "of"}} вернет: "использование вместо [] ", а не ожидаемый результат:" используйте {} вместо [] "
theosp
5
О, в этом есть смысл. Было бы неплохо заявить об этом как о SUBSTRING_THAT_NEVER_OCCURSмысли.
Дан Абрамов
-1

Вы можете просто сделать это:

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

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

И он достигнет места назначения как абстракция функции sjare.

Саад Хаснаин Хан
источник
-2

Это плохая идея, но работает:

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

а также

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

источник