Làm cách nào để thêm nhiều đối số vào bộ lọc mẫu tùy chỉnh của tôi trong một mẫu django?


89

Đây là bộ lọc tùy chỉnh của tôi:

from django import template

register = template.Library()

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

và đây là những cách tôi đã thử sử dụng nó trong tệp mẫu của mình dẫn đến lỗi:

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

Tôi đã xem xét tài liệusách của django nhưng chỉ tìm thấy ví dụ sử dụng một đối số duy nhất ... liệu có khả thi không?

Câu trả lời:


108

Nó có thể và khá đơn giản.

Django chỉ cho phép một đối số vào bộ lọc của bạn, nhưng không có lý do gì bạn không thể đặt tất cả các đối số của mình vào một chuỗi duy nhất bằng cách sử dụng dấu phẩy để phân tách chúng.

Vì vậy, ví dụ: nếu bạn muốn một bộ lọc kiểm tra xem biến X có trong danh sách [1,2,3,4] hay không, bạn sẽ muốn một bộ lọc mẫu giống như sau:

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

Bây giờ chúng tôi có thể tạo thẻ tạm thời của bạn như sau:

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)

Dòng tạo arg_list là một biểu thức trình tạo chia chuỗi args trên tất cả các dấu phẩy và gọi .strip () để loại bỏ bất kỳ khoảng trắng đầu và cuối nào.

Ví dụ: nếu đối số thứ 3 là int thì chỉ cần làm:

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

Hoặc nếu tất cả chúng đều là int thì:

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

CHỈNH SỬA: bây giờ để trả lời cụ thể câu hỏi của bạn bằng cách sử dụng các cặp khóa, giá trị làm tham số, bạn có thể sử dụng cùng một lớp mà Django sử dụng để phân tích cú pháp các chuỗi truy vấn ra khỏi URL, sau đó cũng có lợi ích là xử lý mã hóa ký tự đúng theo settings.py .

Vì vậy, như với các chuỗi truy vấn, mỗi tham số được phân tách bằng '&':

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

Sau đó, hàm thay thế của bạn bây giờ sẽ giống như sau:

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

Bạn có thể đẩy nhanh quá trình này một số có nguy cơ thực hiện một số thay thế không chính xác:

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

1
Nếu các giá trị này nằm trong các biến làm thế nào để thực hiện điều này ...?
Anto

2
Điều này có vẻ hữu ích, nhưng tôi không thể làm cho nó hoạt động với các biến được truyền. Để làm như vậy, tôi đã sử dụng dấu taghoặc simple_tag- cho phép nhiều biến, thậm chí cả các biến đã đặt tên được chuyển.
Furbeenator

18

Không thể theo phần này của tài liệu:

Bộ lọc tùy chỉnh chỉ là các hàm Python nhận một hoặc hai đối số:

  • Giá trị của biến (đầu vào) - không nhất thiết phải là một chuỗi.
  • Giá trị của đối số - giá trị này có thể có giá trị mặc định hoặc bị loại bỏ hoàn toàn.

Cách tiếp cận của Van Gale sẽ hiệu quả nếu bạn đang sử dụng các chuỗi được mã hóa cứng. Vé Django [ code.djangoproject.com/ticket/1199] hỗ trợ nhiều đối số trong bộ lọc tùy chỉnh và bản vá đã được chấp nhận.
Jeff Bauer

17

Nó dễ dàng như thế này.

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

Thực sự tuyệt vời cảm ơn bạn cho giải pháp này. Tôi đã nâng cấp nó một chút để bạn có thể xâu chuỗi các thông số có độ dài khác nhau. gist.github.com/BrnoPCmaniak/e9552294b3059461f940a47143f58811
Filip Dobrovolný

1
Đây phải là câu trả lời chính xác! Đó là một giải pháp python tuyệt đẹp (có thể không phải là giải pháp django tốt nhất, hãy xem câu trả lời của @dragonroot)
Antoine Draune vào

15

Thay vì một bộ lọc, hãy đăng ký thẻ của bạn dưới dạng một thẻ đơn giản. Chúng có thể có nhiều đối số. Cú pháp để gọi nó sẽ hơi khác một chút, nhưng đó chỉ là sự thay đổi đường cú pháp.


2
Đây là câu trả lời chính xác cho vấn đề của tôi. Để chuyển một biến mẫu vào hàm này, tôi phải sử dụng a simple_tag.
Furbeenator

1
Đây là một giải pháp tốt. Chắc chắn đáng để xem qua các tài liệu django cho thẻ đơn giản: docs.djangoproject.com/en/1.8/howto/custom-template-tags/…
Gunther

6

Nó đơn giản hơn bạn nghĩ

Bạn có thể sử dụng simple_tag cho việc này.

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

Trong Mẫu :

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

LƯU Ý: Đừng quên chạy lại máy chủ.


4

Tính năng này đã được đánh dấu là WONTFIX vào năm 2013 Django's Trac: http://code.djangoproject.com/ticket/1199


Vé đó đã được đóng dưới dạng WONTFIX vào năm ngoái (2013), nhà phát triển của họ đề xuất sử dụng thẻ tùy chỉnh nếu cần nhiều đối số.
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)

Trong mẫu:

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

Sẽ rất tốt nếu bạn giải thích #f4x@SgXXmSmột chút?
Dan Abramov

1
chỉ là một chuỗi ngẫu nhiên được sử dụng làm trình giữ chỗ. Tôi đã chọn chuỗi này vì tôi tin rằng nó không phải là một phần của chuỗi đầu vào. Ví dụ: nếu tôi đã sử dụng "{}" thay vì '# f4x @ SgXXmS' thì {{"sử dụng {} thay vì tắt []" | search: "off" | Replace: "of"}} sẽ trả về: "use of thay vì []" và không phải là kết quả mong đợi: 'sử dụng {} thay vì []'
theosp

5
Ồ điều đó cũng có lý. Có thể tốt khi tuyên bố nó như đã SUBSTRING_THAT_NEVER_OCCURSnghĩ.
Dan Abramov

-1

Bạn chỉ có thể làm điều này đơn giản:

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

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

Và nó sẽ đến đích như là sự trừu tượng của hàm sjare.


-2

Đây là một ý tưởng tồi nhưng hiệu quả:

{{ 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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.