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.