How to pass a variable to {% url %} tag in django?

2019-04-02 02:07发布

问题:

I have 2 views: a and b they all render to one template T. There are also a_2 and b_2 views. And T template should generate urls to the a_2 and b_2 views.

however I cannot use {% url %} because I cannot pass url name as a parametr.

I cannot generate the whole url in views because i should do it multiple times (one on a row in a table - so it could be hundreeds of links)

I do not want to write 2 exactly the same template. So the question is - how to avoid this ?

回答1:

This is fixed in django 1.5.

In versions prior to 1.5 you need to use

{% extends 'base.html' %}

{% load url from future %}

{% url 'name_as_a_string' %}
{% url name_stored_in_variable %}

From https://docs.djangoproject.com/en/dev/releases/1.5/

One deprecated feature worth noting is the shift to “new-style” url tag. Prior to Django 1.3, syntax like {% url myview %} was interpreted incorrectly (Django considered "myview" to be a literal name of a view, not a template variable named myview). Django 1.3 and above introduced the {% load url from future %} syntax to bring in the corrected behavior where myview was seen as a variable.



回答2:

Well, in this case you can either use {% if %} tag and add some condition to it (and maybe some varianbles to the context) or write a custom url tag.

myapp
    templatetags
        __init__.py
        myapp_urls.py

myapp_urls.py

from django import template
from django.template import Context
from django.template.defaulttags import register

@register.tag(name="custom_url")
def render_map(parser, token):
    contents, url_name = token.split_contents()
    return CustomURLNode(url_name)

class CustomURLNode(template.Node):
    def __init__(self, url_name):
        self.url_name = template.Variable(url_name)

    def render(self, context):
        return reverse(url_name.resolve(context))

In template:

{% load myapp_urls %}

{% custom_url myvar %}

This is untested code and might contain bugs, but writing custom template tags should be a good solution.