Làm cách nào để đặt giá trị của biến trong mã mẫu?


216

Nói rằng tôi có một mẫu

<html>
<div>Hello {{name}}!</div>
</html>

Trong khi kiểm tra nó, sẽ rất hữu ích khi xác định giá trị của biến mà không cần chạm vào mã python gọi mẫu này. Vì vậy, tôi đang tìm kiếm một cái gì đó như thế này

{% set name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>

Có một cái gì đó như thế này tồn tại trong Django?

Câu trả lời:


327

Bạn có thể sử dụng withthẻ mẫu.

{% with name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>
{% endwith %}

35
Nhưng bạn có thể thay đổi giá trị của biến trong với?
David Wong

2
Có vẻ như bạn không thể khai báo một container (tôi đã thử danh sách và tuple) trong một mệnh đề có
Vladislav Iv biếnin 18/03/2015

Nếu bạn cần khai báo một danh sách, hãy sử dụng make_list. docs.djangoproject.com/en/1.9/ref/temsheet/builtins/#make-list
MrValdez

3
Jinja nói rằng {% đặt myvar = value%} tại sao nó không hoạt động trong django?
thánh

3
@holms Vì Django không sử dụng Jinja :-) docs.djangoproject.com/en/1.7/topics/temsheet
Elimisteve

50

Tạo thẻ mẫu:

Ứng dụng nên chứa một templatetagsthư mục, ở mức độ tương tự như models.py, views.py, vv Nếu điều này không tồn tại, tạo ra nó - đừng quên các __init__.pytập tin để đảm bảo các thư mục được xử lý như là một gói Python.

Tạo một tệp có tên define_action.pybên trong thư mục templatetags với mã sau:

from django import template
register = template.Library()

@register.simple_tag
def define(val=None):
  return val

Lưu ý: Máy chủ phát triển sẽ không tự động khởi động lại. Sau khi thêm templatetagsmô-đun, bạn sẽ cần khởi động lại máy chủ của mình trước khi bạn có thể sử dụng các thẻ hoặc bộ lọc trong các mẫu.


Sau đó, trong mẫu của bạn, bạn có thể gán giá trị cho ngữ cảnh như sau:

{% load define_action %}
{% if item %}

   {% define "Edit" as action %}

{% else %}

   {% define "Create" as action %}

{% endif %}


Would you like to {{action}} this item?

2
trong trường hợp của tôi sau vòng lặp này sẽ trả về giá trị cũ :(
holms 13/03/18

7
Trong phiên bản mới nhất, có vẻ như bạn có thể sử dụng Simple_tag thay vì gán_tag (và nó hoạt động với tôi).
Katharine

Vấn đề tôi nhận được với giải pháp này là nó xuất hiện, rằng bạn không thể ghi đè các giá trị.
Jakub Jabłoński

nếu bạn muốn sử dụng kỹ thuật này để thiết lập một danh sách thay vì chỉ một giá trị, hãy kiểm tra điều này: stackoverflow.com/a
432407158/2193235

nếu bạn đang đặt biến là một số nguyên và bạn muốn tăng nó (ví dụ), bạn cần sử dụng add: {% define counter|add:1 as counter %}. Tương tự cho các hoạt động khác.
msb

35

Một cách khác không yêu cầu bạn đặt mọi thứ vào khối "với" là tạo một thẻ tùy chỉnh có thêm một biến mới vào ngữ cảnh. Như trong:

class SetVarNode(template.Node):
    def __init__(self, new_val, var_name):
        self.new_val = new_val
        self.var_name = var_name
    def render(self, context):
        context[self.var_name] = self.new_val
        return ''

import re
@register.tag
def setvar(parser,token):
    # This version uses a regular expression to parse tag contents.
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
    m = re.search(r'(.*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    new_val, var_name = m.groups()
    if not (new_val[0] == new_val[-1] and new_val[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
    return SetVarNode(new_val[1:-1], var_name)

Điều này sẽ cho phép bạn viết một cái gì đó như thế này trong mẫu của bạn:

{% setvar "a string" as new_template_var %}

Lưu ý rằng hầu hết những thứ này được lấy từ đây


Làm thế nào về việc gán các biến cho các biến khác có trong bối cảnh? Và trên một lưu ý khác: cho phép các mẫu tự ý gán các biến bối cảnh mà không cần kiểm tra xem chúng có tồn tại hay không có ý nghĩa bảo mật. Theo tôi, một cách tiếp cận hợp lý hơn sẽ là kiểm tra bối cảnh cho biến trước khi cố gắng gán nó:
ngâm

if context.get (self.var_name): nâng cao SuspiousOperation ("Cố gắng gán biến từ mẫu đã có trong ngữ cảnh")
ngâm

27

Có những mánh khóe giống như mô tả của John; tuy nhiên, ngôn ngữ mẫu của Django theo thiết kế không hỗ trợ cài đặt một biến (xem hộp "Triết lý" trong tài liệu về Django cho các mẫu ).
Do đó, cách được đề xuất để thay đổi bất kỳ biến nào thông qua việc chạm vào mã Python.


7
Cảm ơn con trỏ. Từ quan điểm của một nhà thiết kế, đôi khi dễ dàng nhanh chóng đặt một biến để kiểm tra các trạng thái khác nhau của trang trong khi thiết kế nó. Không đề xuất thực hành này được sử dụng trong một mã đang chạy.
Alexis

2
thẻ "với" được chấp nhận trong django1.0. Vì vậy, có vẻ như cuối cùng họ đang sửa đổi triết lý của họ :).
Evgeny

2
Như một vấn đề thực tế, thẻ "với" chỉ dành cho bí danh. Điều này có thể có một tác động lớn đến hiệu suất (và cả khả năng đọc!) Nhưng nó không thực sự thiết lập một biến trong các thuật ngữ lập trình truyền thống.
cướp

12

Giải pháp tốt nhất cho việc này là viết một tùy chỉnh assignment_tag. Giải pháp này sạch hơn so với sử dụng withthẻ vì nó đạt được sự tách biệt rất rõ ràng giữa logic và kiểu dáng.

Bắt đầu bằng cách tạo tệp thẻ mẫu (ví dụ appname/templatetags/hello_world.py:):

from django import template

register = template.Library()

@register.assignment_tag
def get_addressee():
    return "World"

Bây giờ bạn có thể sử dụng get_addresseethẻ mẫu trong các mẫu của bạn:

{% load hello_world %}

{% get_addressee as addressee %}

<html>
    <body>
        <h1>hello {{addressee}}</h1>
    </body>
</html>

3
Đối với những người sử dụng các phiên bản Django mới hơn, nó được gọi là Simple_tag ngay bây giờ! Tiết kiệm thời gian để tìm hiểu tại sao "đăng ký .." không được nhận ra trong mã của bạn ...
kaya

11

Có lẽ defaultbộ lọc mẫu không phải là một tùy chọn vào năm 2009 ...

<html>
<div>Hello {{name|default:"World"}}!</div>
</html>

Tôi phải nói rằng đây là những gì tôi đang tìm kiếm! Nó có thể được cũng được sử dụng với với : {% with state=form.state.value|default:other_context_variable %}thay vì other_context_variablechúng ta cũng có thể sử dụng bất kỳ 'string_value'cũng
Saurav Kumar

Nhưng nó sẽ in nó và tôi cần lưu nó để sử dụng sau
holms 10/03/18

4

Đây không phải là một ý tưởng tốt nói chung. Thực hiện tất cả logic trong python và truyền dữ liệu vào mẫu để hiển thị. Mẫu nên đơn giản nhất có thể để đảm bảo những người làm việc trên thiết kế có thể tập trung vào thiết kế thay vì lo lắng về logic.

Để đưa ra một ví dụ, nếu bạn cần một số thông tin dẫn xuất trong một mẫu, tốt hơn là đưa nó vào một biến trong mã python và sau đó chuyển nó cùng với mẫu.


3

Sử dụng câu lệnh with .

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

Tôi không thể ngụ ý mã trong đoạn đầu tiên trong câu trả lời này . Có thể ngôn ngữ mẫu đã không dùng định dạng cũ.


2

Trong mẫu của bạn, bạn có thể làm như thế này:

{% jump_link as name %}
{% for obj in name %}
    <div>{{obj.helo}} - {{obj.how}}</div>
{% endfor %}

Trong thẻ mẫu của bạn, bạn có thể thêm một thẻ như thế này:

@register.assignment_tag
def jump_link():
    listArr = []
    for i in range(5):
        listArr.append({"helo" : i,"how" : i})
    return listArr
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.