Bir django şablonundaki özel şablon filtreme nasıl birden çok argüman eklerim?


91

İşte özel filtrem:

from django import template

register = template.Library()

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

ve bunu şablon dosyamda bir hatayla sonuçlanan kullanmayı denediğim yöntemler:

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

Django'nun belgelerine ve kitabına baktım ama sadece tek bir argüman kullanarak örnek buldum ... bu mümkün mü?

Yanıtlar:


108

Mümkün ve oldukça basit.

Django, filtreniz için yalnızca bir argümana izin verir, ancak tüm argümanlarınızı virgül kullanarak ayırmak için tek bir dizeye koyamamanız için hiçbir neden yoktur.

Örneğin, X değişkeninin listede [1,2,3,4] olup olmadığını kontrol eden bir filtre istiyorsanız, şuna benzer bir şablon filtresi isteyeceksiniz:

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

Şimdi şablon etiketinizi şu şekilde oluşturabiliriz:

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'i oluşturan satır, args dizesini tüm virgüllere bölen ve baştaki ve sondaki boşlukları kaldırmak için.

Örneğin, 3. argüman bir int ise, sadece şunu yapın:

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

Ya da hepsi ints ise:

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

DÜZENLEME: şimdi, anahtar, değer çiftlerini parametre olarak kullanarak sorunuzu özel olarak yanıtlamak için, Django'nun URL'lerden sorgu dizelerini ayrıştırmak için kullandığı sınıfı kullanabilirsiniz; bu, daha sonra ayarlarınıza göre karakter kodlamasını düzgün bir şekilde işleme avantajına da sahiptir.py .

Dolayısıyla, sorgu dizelerinde olduğu gibi, her parametre "&" ile ayrılır:

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

Daha sonra değiştirme işleviniz şimdi şöyle görünecektir:

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

Bazı yanlış değişiklikler yapma riskiyle bunu biraz hızlandırabilirsiniz:

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

1
Bunların değerleri değişkenler içindeyse, bu nasıl uygulanır ...?
Anto

2
Bu yardımcı görünüyordu, ancak aktarılan değişkenlerle çalışmasını sağlayamadım. Bunu yapmak için, birden çok değişkene, hatta adlandırılmış değişkenlerin aktarılmasına izin veren bir tagveya simple_tag- kullandım .
Furbeenator

18

Belgelerin bu bölümüne göre mümkün değil :

Özel filtreler, bir veya iki argüman alan Python işlevleridir:

  • Değişkenin değeri (girdi) - mutlaka bir dize değil.
  • Bağımsız değişkenin değeri - bu varsayılan bir değere sahip olabilir veya tamamen dışarıda bırakılabilir.

Sabit kodlanmış dizeler kullanıyorsanız Van Gale'in yaklaşımı işe yarayacaktır. Django bileti [ code.djangoproject.com/ticket/1199] , özel bir filtrede birden çok argümanı destekler ve bir yama kabul edildi.
Jeff Bauer

17

Bu kadar kolay.

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

Bu çözüm için gerçekten çok teşekkür ederim. Farklı uzunluklarda parametreleri zincirleyebilmeniz için onu biraz yükselttim. gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
Filip Dobrovolný

1
Bu doğru cevap olmalı! Bu güzel bir python çözümü (belki de en iyi django çözümü değil, bkz. @Dragonroot yanıtı)
Antoine Draune

15

Bir filtre yerine etiketinizi basit bir etiket olarak kaydedin. Bunlar birden fazla argüman alabilir. Onu çağırmanın sözdizimi biraz farklı olacaktır, ama bu sadece sözdizimsel şeker değişimi.


2
Sorunum için doğru cevap buydu. Bu işleve bir şablon değişkeni geçirmek için bir simple_tag.
Furbeenator

1
Bu iyi bir çözüm. Basit etiket için django belgelerine göz atmaya kesinlikle değer: docs.djangoproject.com/en/1.8/howto/custom-template-tags/…
Gunther

6

Düşündüğünüzden daha basit

Bunun için simple_tag kullanabilirsiniz .

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

Şablonda :

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

NOT: Sunucuyu yeniden çalıştırmayı unutmayın.



3

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

Şablonda:

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

#f4x@SgXXmSBiraz açıklasan iyi olur mu?
Dan Abramov

1
sadece yer tutucu olarak kullanılan rastgele bir dize. Bu dizeyi seçtim çünkü girdi dizesinin bir parçası olmayacağına inanıyordum. Örneğin, '# f4x @ SgXXmS' yerine "{}" kullandıysam {{"{} yerine kapalı []" | arama: "kapalı" | değiştir: "/"}} şunu döndürür: "kullanımı [] yerine "ve beklenen sonuç değil:" [] yerine {} kullanın "
theosp

6
Oh, bu mantıklı. SUBSTRING_THAT_NEVER_OCCURSDüşündüğünü söylemek güzel olabilir .
Dan Abramov

-1

Bunu basitçe yapabilirsiniz:

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

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

Ve fonksiyonun soyutlaması olduğu gibi hedefe ulaşacaktır sjare.


-2

Bu kötü bir fikir ama işe yarıyor:

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

ve

@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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.