为什么我的上下文变量没有正确呈现?

时间:2012-03-15 23:40:12

标签: django django-templates

参考:How do I construct a Django reverse/url using query args?

这是somepage.html

<a href={% query_urls from={{from}} to={{to}} %}> LOL LOSER</a>

首先转到somepage次观看,然后点击任意按钮将重定向到move次观看。

def move(request):
    to = request.GET.get('to', 'None')
    ffrom = request.GET.get('from', 'None')
    #raise AssertionError(ffrom)
    return render_to_response(request, "move.html", {'to': to, 'from': ffrom})

def somepage(request):
    to = '../mydir'
    ffrom = './heere.py'
    return render_to_response(request, "somepage.html", {'to': to, 'from': ffrom})

而不是像 http://localhost/web/move?from=./here.py&to=../mydir 我明白了

http://localhost/web/move?from={{from}}&to={{to}}

这些上下文变量根本没有得到渲染,可能是因为自定义标记(应用于somepage视图)将所有参数都作为字符串。如何强制首先渲染它?

感谢。


**编辑**小问题: 如果我想实现这个目标

url(r"^search/<?P(cbid)\d+>/", 'views.search', name='search')

如果我把它放在模板

中,我会得到Malformed arguments to query_urls tag
<a href={% query_url 'search' 12456 from=from to=to %}> MY LINK </a>

编写自定义标记的通用方法是什么?

目前,这就是我做的......哪个有效...

def render(self, context):
    view_name = self.view_name.resolve(context)
    kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context))
                   for k, v in self.kwargs.items()])
    cbid = kwargs['cbid']
    kwargs = sorted(kwargs.items(), key=lambda x:x[0]) # sorted and generate a list of 2-tuple
    # kwargs query set now contains no cbid
    kwargs = [ value for index, value in enumerate(kwargs) if value[0] != 'cbid']

    #raise AssertionError(urllib.urlencode(kwargs))
    return (reverse(view_name, args=[(cbid),], current_app=context.current_app)
            + '?' + urllib.urlencode(kwargs))

我想让它更通用,匹配任何模式,而不仅仅是cbid。

<a href={% query_url 'search' cbid=12456 from=from to=to %}> MY LINK </a>

一种愚蠢的方式(也许唯一的方法)就是在模板中写出这样的东西

{% query_url 'view_func' args=[(cbid, some_text, more_text,)], from=foo to=bar %}

其中args在字面上被视为args列表,就像在常规python函数中一样。我们可能会eval将其放入列表而不是文字字符串。

2 个答案:

答案 0 :(得分:2)

我认为您调用的query_url模板标记是answer you linked to中的myurl标记。该模板标记不会针对模板上下文解析其参数。这是您可能尝试的更完整的实现,它还执行reverse查找以获取将查询参数附加到的URL。

在Django 1.4中,这是对the simple_tag decorator

的简单使用
from django import template

register = template.Library()

@register.simple_tag
def query_url(view_name, **kwargs):
    """
    Returns an absolute URL matching given view, with query parameters
    appended. For example, if you have this URL in your configuration:

        ('^search/$', 'myapp.search')

    then in a template you can create a search link like this:

        {% query_url 'myapp.search' q=value1 id=value2 %}

    The first argument is a path to a view. The other arguments become
    query parameters, so the URL will look something like:
    ``/search/?q=querystring&id=123``.
    """
    return reverse(view_name) + '?' + urllib.urlencode(kwargs)

但是在Django 1.3中你必须详细拼写:

from django import template
from django.core.urlresolvers import reverse
from django.template import Library, Node, TemplateSyntaxError
from django.utils.encoding import smart_str
import re
import urllib

register = template.Library()

class QueryURLNode(Node):
    def __init__(self, view_name, kwargs):
        self.view_name = view_name
        self.kwargs = kwargs

    def render(self, context):
        view_name = self.view_name.resolve(context)
        kwargs = dict([(smart_str(k, 'ascii'), v.resolve(context))
                       for k, v in self.kwargs.items()])
        return (reverse(view_name, current_app=context.current_app)
                + '?' + urllib.urlencode(kwargs))

@register.tag
def query_url(parser, token):
    """
    Returns an absolute URL matching given view, with query parameters
    appended. For example, if you have this URL in your configuration:

        ('^search/$', 'myapp.search')

    then in a template you can create a search link like this:

        {% query_url 'myapp.search' q=object.name id=object.id %}

    The first argument is a path to a view. The other arguments become
    query parameters, so the URL will look something like:
    ``/search/?q=name&id=123``.
    """
    bits = token.split_contents()
    if len(bits) < 2:
        raise TemplateSyntaxError("'%s' takes at least one argument"
                                  " (path to a view)" % bits[0])
    viewname = parser.compile_filter(bits[1])
    kwargs = {}
    kwarg_re = re.compile(r"(\w+)=(.+)")
    for bit in bits[2:]:
        match = kwarg_re.match(bit)
        if not match:
            raise TemplateSyntaxError("Malformed arguments to %s tag" % bits[0])
        name, value = match.groups()
        kwargs[name] = parser.compile_filter(value)
    return QueryURLNode(viewname, kwargs)

答案 1 :(得分:1)

问题是您没有在自定义标记中解析上下文变量。

阅读本文:Passing template variable to a tag