2009-06-23 35 views
5

tôi đang làm một cái gì đó như:Xác định "biến toàn cầu" trong Django các mẫu

{% extends 'base.html' %} 
{% url myapp.views.dashboard object as object_url %} 
{% block sidebar %} 
... {{ object_url }} ... 
{% endblock %} 
{% block content %} 
... {{ object_url }} ... 
{% endblock %} 

tài liệu Django nói url templatetag có thể định nghĩa một biến trong bối cảnh, nhưng tôi không nhận được bất kỳ giá trị cho object_url trong những điều sau đây khối.

Nếu tôi đặt templatetag url vào đầu mỗi khối, nó hoạt động, nhưng tôi không muốn "lặp lại bản thân mình".

Có ai biết giải pháp tốt hơn không?

Trả lời

7

Nếu URL là chế độ xem cụ thể, bạn có thể chuyển URL từ chế độ xem của mình. Nếu URL cần phải được toàn cầu thực sự trong các mẫu của bạn, bạn có thể đặt nó trong a context processor:

def object_url(request): 
    return {'object_url': reverse('myapp.views.dashboard')} 
+0

+1, bạn' nhanh hơn tôi. – SingleNegationElimination

+0

Um, nhiều chế độ xem sử dụng biến này nhưng không phải tất cả. Ngoài ra, tôi đang sử dụng cùng một mẫu cho một loại biến được xác định bởi templatetags tùy chỉnh của tôi. Các trường hợp trên chỉ đơn giản hóa, vì vậy tôi nghĩ rằng nó không thích hợp để áp dụng giải pháp của bạn như nó được. – Achimnol

+3

Thậm chí nếu nó không được sử dụng trong mọi mẫu, nó không làm hại bất cứ thứ gì để đưa nó vào bộ xử lý ngữ cảnh ... trừ khi nó thực hiện tra cứu cơ sở dữ liệu, trong trường hợp đó nó có thể tác động đến hiệu suất trang. –

0

Vâng, đây là loại lạm dụng mẫu thừa kế, nhưng bạn có thể sử dụng {{block.super}} đặt object_url thành các khối của bạn.

Nói cách khác, trong mẫu giữa trình độ của bạn làm:

{% block sidebar %}{{ object_url }}{% endblock %} 
{% block content %}{{ object_url }}{% endblock %} 

Và sau đó trong các mẫu khối của bạn sử dụng:

{% block sidebar %} 
... {{ block.super }}... 
{% endblock %} 

Nó không phải là một ý tưởng tuyệt vời bởi vì nó ngăn không cho bạn đặt bất cứ điều gì bên cạnh {{ object_url }} vào khối của bạn ... nhưng nó hoạt động. Chỉ cần không nói với bất cứ ai bạn đã nhận nó từ tôi!

+0

Tôi nên thêm cá nhân tôi thích rõ ràng và thực hiện tải trong mỗi mẫu. Làm cho nó dễ dàng hơn cho tôi để xem chính xác nơi dữ liệu của tôi đến từ đâu. –

0

Trong mọi mẫu được kế thừa, bất kỳ mã nào bên ngoài khối định nghĩa lại đều không được thực hiện. Vì vậy, trong ví dụ của bạn, bạn phải gọi {% url %} thẻ bên trong mỗi khối hoặc sử dụng bộ xử lý ngữ cảnh để đặt biến "chung".

2

Có vẻ như điều này đã được trả lời trước đây, nhưng có một giải pháp thay thế. Đó là một điều để sử dụng một bộ xử lý ngữ cảnh để theo dõi một cái gì đó được xác định từ bên ngoài mẫu, nhưng đôi khi bạn muốn đếm số lần hai vòng đi qua, hoặc một cái gì đó như thế. Có một cách khác:

class GlobalVariable(object): 
    def __init__(self, varname, varval): 
    self.varname = varname 
    self.varval = varval 
    def name(self): 
    return self.varname 
    def value(self): 
    return self.varval 
    def set(self, newval): 
    self.varval = newval 

class GlobalVariableSetNode(template.Node): 
    def __init__(self, varname, varval): 
    self.varname = varname 
    self.varval = varval 
    def render(self, context): 
    gv = context.get(self.varname, None) 
    if gv: 
     gv.set(self.varval) 
    else: 
     gv = context[self.varname] = GlobalVariable(self.varname, self.varval) 
    return '' 
def setglobal(parser, token): 
    try: 
    tag_name, varname, varval = token.contents.split(None, 2) 
    except ValueError: 
    raise template.TemplateSyntaxError("%r tag requires 2 arguments" % token.contents.split()[0]) 
    return GlobalVariableSetNode(varname, varval) 
register.tag('setglobal', setglobal) 

class GlobalVariableGetNode(template.Node): 
    def __init__(self, varname): 
    self.varname = varname 
    def render(self, context): 
    try: 
     return context[self.varname].value() 
    except AttributeError: 
     return '' 
def getglobal(parser, token): 
    try: 
    tag_name, varname = token.contents.split(None, 1) 
    except ValueError: 
    raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0]) 
    return GlobalVariableGetNode(varname) 
register.tag('getglobal', getglobal) 

class GlobalVariableIncrementNode(template.Node): 
    def __init__(self, varname): 
    self.varname = varname 
    def render(self, context): 
    gv = context.get(self.varname, None) 
    if gv is None: 
     return '' 
    gv.set(int(gv.value()) + 1) 
    return '' 
def incrementglobal(parser, token): 
    try: 
    tag_name, varname = token.contents.split(None, 1) 
    except ValueError: 
    raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0]) 
    return GlobalVariableIncrementNode(varname) 
register.tag('incrementglobal', incrementglobal) 

này cho phép bạn sử dụng nó trong một khuôn mẫu như thế này:

{% setglobal ii 0 %} 
... 
{% for ... %} 
    {% incrementglobal ii %} 
    current={% getglobal ii %} 
{% endfor %} 
... 
{% for ... %} 
    {% incrementglobal ii %} 
    current={% getglobal ii %} 
{% endfor %} 
... 
total of 2 loops={% getglobal ii %} 
... 
{% setglobal ii 0 %} 
... 
do something else now that {% getglobal ii %} is back to 0 
1

Bạn có thể viết một mẫu tùy chỉnh tag:

@register.simple_tag(takes_context=True) 
def set_global_context(context, key, value): 
    """ 
    Sets a value to the global template context, so it can 
    be accessible across blocks. 

    Note that the block where the global context variable is set must appear 
    before the other blocks using the variable IN THE BASE TEMPLATE. The order 
    of the blocks in the extending template is not important. 

    Usage:: 
     {% extends 'base.html' %} 

     {% block first %} 
      {% set_global_context 'foo' 'bar' %} 
     {% endblock %} 

     {% block second %} 
      {{ foo }} 
     {% endblock %} 
    """ 
    context.dicts[0][key] = value 
    return '' 
+0

Tôi đã sử dụng cách tiếp cận này bản thân mình và nó hoạt động tuyệt vời cho mã và khả năng đọc. Một biến toàn cục được chỉnh sửa ngẫu nhiên trong suốt các khuôn mẫu có thể rất khó gỡ lỗi. Tạo một máy trạng thái bằng cách sử dụng một mẫu giữ logic ở một nơi, điều này có nhiều lợi ích. –

Các vấn đề liên quan