hek*_*ran 13 django django-templates
我希望能够将模板中的变量设置为字符串值.我写了一个标签,但它似乎没有改变上下文.预期用途是:
{% define "a string" as my_var %}
Run Code Online (Sandbox Code Playgroud)
更新(已解决):
class DefineNode(Node):
def __init__(self, var, name):
self.var = var
self.name = name
def __repr__(self):
return "<DefineNode>"
def render(self, context):
context[self.name] = self.var
return ''
@register.tag
def define(parser, token):
"""
Adds a name to the context for referencing an arbitrarily defined string.
For example:
{% define "my_string" as my_string %}
Now anywhere in the template:
{{ my_string }}
"""
bits = list(token.split_contents())
if (len(bits) != 4 or bits[2] != "as") or \
not (bits[1][0] in ('"', "'") and bits[1][-1] == bits[1][0]):
raise TemplateSyntaxError("%r expected format is '\"string\" as name'" % bits[0])
else:
value = bits[1][1:-1]
name = bits[3]
return DefineNode(value, name)
Run Code Online (Sandbox Code Playgroud)
kir*_*ril 18
Django已经考虑了这个特殊情况并提供了分配标签,这是一种注册标签的特殊方式,可以在上下文中设置变量.
在这种情况下,您无需关心检索,更新和保存上下文.你只需这样做:
@register.assignment_tag
def define(the_string):
return the_string
Run Code Online (Sandbox Code Playgroud)
你可以用同样的方式使用它,但它更清洁:
{% define "a string" as my_var %}
Run Code Online (Sandbox Code Playgroud)
这是您需要的所有代码.
编辑:正如Dirk Bergstrom指出的那样,因为版本django 1.9 assignment_tag
已被弃用.simple_tag
是一个完美的替代品.
@register.simple_tag
def define(the_string):
return the_string
Run Code Online (Sandbox Code Playgroud)
Joh*_*Mee 11
答案隐藏在文档中更复杂的current_time示例中.
问题
You want to add a variable to the context. But you don't want to go back and add that variable to all the views which call all the templates which invoke the tag. You just want a tag which can add some data to the context wherever its wanted. I'm looking for this kind of thing when rendering those random distractions which get dropped into sidebars and aren't specifically related to the work of the main view, for example.
Method
To inject a variable to the context you need access to the context. To do that your custom tag will inject a node which added the data to the template context.
Example
This example adds a "coming_events" queryset to the context then loops over each result. It does that by declaring a custom tag which renders a node which adds a queryset to the context.
from django import template
from apps.events.models import Event
register = template.Library()
@register.tag
def coming_events(parser, token):
return EventNode()
class EventNode(template.Node):
def render(self, context):
context['coming_events'] = Event.objects.all()
return ''
Run Code Online (Sandbox Code Playgroud)
You'd use it like this:
{% load events %}
{% coming_events %}
{% for event in coming_events %}
<div class="eventItem">
<p>{{event.title}} {{event.data}}</p>
</div>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
Extra Credit
If you're really keen to be able to name the variable arbitrarily eg {% coming_events as events %} then look closely at the example in the documentation and note how they split the token into what's before the ' as ' and what's after and use the latter part to name the context variable. You'd have to implement that.
Note that if I wound up putting the HTML for each event into its own dedicated template then I'd be better off just following the standard inclusion tag example in the documentation. This solution is suggested for when you want the data without any baggage.
您无需编写自己的标签。内置{% with %}
标签就是这样做的。
如果您希望变量在其他模板块中可用,您应该查看http://od-eon.com/blogs/liviu/scope-variables-template-blocks/.特别是,在自定义标记代码中,您应该替换:
context[some_var_name] = some_val
Run Code Online (Sandbox Code Playgroud)
有:
context.dicts[0][some_var_name] = some_val
Run Code Online (Sandbox Code Playgroud)
这将成功(虽然它可能是一个丑陋的技巧,你应该考虑替代品).
归档时间: |
|
查看次数: |
22905 次 |
最近记录: |