Як додати кілька аргументів до мого користувацького фільтра шаблону в шаблоні 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 - це вираз генератора, який розділяє рядок аргументів на всі коми і викликає .strip (), щоб видалити пробіли, що ведуть і закінчують.

Якщо, наприклад, 3-й аргумент є int, тоді просто виконайте:

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

Або якщо всі вони є ints роблять:

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
Якщо значення для них знаходяться у змінних, як це реалізувати ...?
Анто

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/…
Гюнтер

5

Це простіше, ніж ви думаєте. Для

цього можна використовувати 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 у 2013 Django's Trac: http://code.djangoproject.com/ticket/1199


Цей квиток було закрито як WONTFIX минулого року (2013), їх розробник пропонує використовувати спеціальний тег, якщо потрібно кілька аргументів.
Paul Lo,

3

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

У шаблоні:

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

Було б непогано, якби ви #f4x@SgXXmSтрохи пояснили ?
Ден Абрамов

1
просто випадковий рядок, який використовується як заповнювач. Я вибрав цей рядок, бо вважав, що він не буде частиною вхідного рядка. Якщо, наприклад, я використав "{}" замість "# f4x @ SgXXmS", {{"використовувати {} замість вимкнено []" | пошук: "вимкнено" | замінити: "з"}} повернеться: "використання замість [] ", а не очікуваний результат:" використовувати {} замість [] "
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.