2012-03-15 96 views
1

參考: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意見)需要所有的參數都是字符串。我如何強制先渲染它?

謝謝。


**編輯**小問題: 如果我想,如果我把這個模板

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

實現這一

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

我得到Malformed arguments to query_urls tag什麼的通用方式寫我的自定義標籤,讓這個?

目前,這是我做什麼......這作品...

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> 

啞的方式(也可能是唯一的方法)就是寫這樣的事情在參數表是從字面上理解爲參數的個數名單就像一個普通的Python函數模板

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

。我們大概可以將eval這個變成一個列表而不是一個文字字符串。

+1

沒有必要爲'{{}}'的模板標籤:你應該只寫'{%來自= query_urls從到=到%}' – 2012-03-15 23:45:30

+0

@GarethRees謝謝。我只是試了一下。它不起作用。它給我'from = from&to =到' – User007 2012-03-15 23:52:11

+1

啊,我看到:你正在使用你鏈接到的問題中的myurl模板標籤。這不會做可變評估。我會寫一個詳細的答案。 – 2012-03-16 00:24:46

回答

2

我認爲,我們在調用query_url模板標籤是從answer you linked tomyurl標籤。該模板標籤不能根據模板上下文解析其參數。下面是一個更完整的實現,您可以嘗試,也可以使用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) 
+0

爲好的演示+1! – CppLearner 2012-03-16 01:25:27

+0

謝謝。爲什麼我們使用'parser.compile_filter'?這是做什麼的?謝謝。 – User007 2012-03-16 01:39:58

+1

它構造了一個['FilterExpression'](https://code.djangoproject.com/browser/django/trunk/django/template/base.py#L507)「解析變量標記及其可選過濾器」的對象。所以你可以在標籤的參數上使用模板過濾器:'{%query_url'myapp.view'a = var | upper b = var | truncatechars:10%}'或其他。 – 2012-03-16 09:55:59