Bagaimana cara menambahkan beberapa argumen ke filter template kustom saya di template django?

89

Ini filter khusus saya:

from django import template

register = template.Library()

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

dan berikut adalah cara saya mencoba menggunakannya di file template saya yang menghasilkan kesalahan:

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

Saya melihat ke dalam dokumen dan buku Django tetapi hanya menemukan contoh menggunakan satu argumen ... apakah itu mungkin?

bchhun
sumber

Jawaban:

108

Itu mungkin dan cukup sederhana.

Django hanya memperbolehkan satu argumen ke filter Anda, tetapi tidak ada alasan Anda tidak bisa meletakkan semua argumen Anda ke dalam satu string menggunakan koma untuk memisahkannya.

Jadi misalnya, jika Anda menginginkan filter yang memeriksa apakah variabel X ada dalam daftar [1,2,3,4] Anda akan menginginkan filter template yang terlihat seperti ini:

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

Sekarang kami dapat membuat templatetag Anda seperti ini:

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)

Baris yang membuat arg_list adalah ekspresi generator yang membagi string args pada semua koma dan panggilan .strip () untuk menghapus spasi di depan dan di belakangnya.

Jika, misalnya, argumen ke-3 adalah int maka lakukan saja:

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

Atau jika semuanya int lakukan:

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

EDIT: sekarang untuk secara khusus menjawab pertanyaan Anda dengan menggunakan kunci, pasangan nilai sebagai parameter, Anda dapat menggunakan kelas yang sama yang Django gunakan untuk mengurai string kueri dari URL, yang kemudian juga memiliki keuntungan menangani pengkodean karakter dengan benar sesuai dengan pengaturan Anda. .

Jadi, seperti string kueri, setiap parameter dipisahkan oleh '&':

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

Kemudian fungsi ganti Anda sekarang akan terlihat seperti ini:

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

Anda dapat mempercepat ini dengan risiko melakukan beberapa penggantian yang salah:

qs = QueryDict(args)
return value.replace(qs.get('cherche',''), qs.get('remplacement',''))
Van Gale
sumber
1
Jika nilai-nilai ini ada dalam variabel bagaimana menerapkan ini ...?
Anto
2
Ini sepertinya membantu, tetapi saya tidak bisa membuatnya berfungsi dengan variabel yang dilewatkan. Untuk melakukannya, saya telah menggunakan tagatau simple_tag- yang memungkinkan beberapa variabel, bahkan variabel bernama untuk dilewatkan.
Furbeenator
18

Tidak memungkinkan menurut bagian dokumen ini:

Filter khusus hanyalah fungsi Python yang mengambil satu atau dua argumen:

  • Nilai variabel (input) - tidak harus berupa string.
  • Nilai argumen - ini dapat memiliki nilai default, atau tidak digunakan sama sekali.
Jeff Bauer
sumber
Pendekatan Van Gale akan berhasil jika Anda menggunakan string hard-code. Tiket Django [ code.djangoproject.com/ticket/1199] mendukung banyak argumen dalam filter kustom dan tambalan telah diterima.
Jeff Bauer
17

Semudah ini.

@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 }}
gshmu
sumber
Sangat bagus, terima kasih atas solusi ini. Saya telah meningkatkannya sedikit sehingga Anda dapat merangkai parameter dengan panjang yang berbeda. gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
Filip Dobrovolný
1
Ini seharusnya jawaban yang benar! Ini adalah solusi python yang indah (mungkin bukan solusi django terbaik, lihat jawaban @dragonroot)
Antoine Draune
15

Alih-alih sebagai filter, daftarkan tag Anda sebagai tag sederhana. Itu bisa membutuhkan banyak argumen. Sintaks untuk memanggilnya akan sedikit berbeda, tapi itu hanya perubahan gula sintaksis.

akar naga
sumber
2
Ini adalah jawaban yang benar untuk masalah saya. Untuk melewatkan variabel template ke dalam fungsi ini, saya harus menggunakan file simple_tag.
Furbeenator
1
Ini adalah solusi yang bagus. Sangatlah berharga untuk memeriksa dokumen django untuk tag sederhana: docs.djangoproject.com/en/1.8/howto/custom-template-tags/…
Gunther
6

Ini lebih sederhana dari yang Anda kira.

Anda dapat menggunakan simple_tag untuk ini.

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

Dalam Template :

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

CATATAN: Jangan lupa untuk menjalankan ulang server.

Sawan Chauhan
sumber
4

Fitur ini telah ditandai sebagai WONTFIX pada 2013 Django's Trac: http://code.djangoproject.com/ticket/1199

bchhun
sumber
Tiket itu ditutup sebagai WONTFIX tahun lalu (2013), pengembang mereka menyarankan menggunakan tag khusus jika perlu banyak argumen.
Paul Lo
3

<situs-saya> /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)

Di dalam template:

{{ "saniel"|search:"s"|replace:"d" }}
theosp
sumber
Alangkah baiknya jika Anda menjelaskan #f4x@SgXXmSsedikit?
Dan Abramov
1
hanya string acak yang digunakan sebagai placeholder. Saya memilih string ini karena saya yakin itu tidak akan menjadi bagian dari string input. Jika misalnya saya telah menggunakan "{}" alih-alih '# f4x @ SgXXmS' {{"use {} bukannya off []" | search: "off" | replace: "of"}} akan menghasilkan: "use of bukannya [] "dan bukan hasil yang diharapkan:" gunakan {} daripada [] "
theosp
5
Oh, masuk akal. Mungkin menyenangkan untuk menyatakannya sebagai SUBSTRING_THAT_NEVER_OCCURSpikiran.
Dan Abramov
-1

Anda cukup melakukan ini:

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

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

Dan itu akan mencapai tujuan sebagai abstraksi fungsinya sjare.

Saad Hasnain Khan
sumber
-2

Ini ide yang buruk tapi berhasil:

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

dan

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

sumber