Как добавить несколько аргументов к моему настраиваемому фильтру шаблона в шаблоне 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, но нашел только пример с одним аргументом ... возможно ли это?

Ответы:


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


Этот билет был закрыт как 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)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.