New url syntax from django 1.3/dev onwards - django

Why did the django core developers allow the url templatetag to point directly to a django view function? (reference - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#url)
{% load url from future %}
{# 1st method: pointing to a view function #}
{% url 'app_views.client' %}
{# 2nd method: pointing to a named url #}
{% url 'myapp:view-name' %}
One can already name the url in urls.py and hence use the 2nd method to point to a specific url. It doesn't feel right to allow developers to actually reference a view function directly from the template.
Does anyone know why this decision was made?

Passing a dotted view function name to the {% url %} template tag is simply the form the template tag took in the earlier days of Django, before you could name URLs. It's still supported, though as you point out, you probably wouldn't use it in a modern application.

URLs in Django are just mappings to views. Therefore, in the template, using a named URL is just indirectly referencing the view anyway.
The exception is where a single view is mapped to by multiple URLs.
Also note that they are planning to change the syntax of the url tag in 1.5. It will take a context variable as the parameter, rather than a string. It will still take views or named URLs though.

Related

Using a variable in a {% url %} when `app_name` has been defined

I am having issues trying to use a Django template variable to form a URL in combination with the app_name attribute.
Currently, I am using a template variable to form a URL
On our page about {{ variable_name }}.
Though I am aware that it is seen as good practice to make a URL more accurate by defining app_name in URLs. e.g.
app_name = "name_of_app"
Meaning that URLs are then written like:
About
Is it possible for me to combine my current code with this approach? To use a variable and the app_name attribute?
I have experimented with this {% url 'NameOfApp:'this_is_a_variable %}, by putting the quote marks in different places, but no success yet.
You need to use the "add" filter as such:
{% url "name_of_app:"|add:variable %}
Django convert all the template tags and variables in to plain text while rendering. We can't directly do that. Try using template filter or with tag.

Is it possible to display a specific block from a template in django?

Just like in html when you reference a section of a page with for instanceVisit the Useful Tips Section
Would there be a way to do a similar thing in django if for instance I wanted to load my page straight to the tips section? I am extending base.html to my home page that has a tips section. Right now i have a static url home i want to do the exact same but with djangos dynamic url something like {% url 'home'/#tips %}
You can just add the fragment identifier right after the URL returned by the {% url %} template tag:
home

Generating a URL in a template that takes project URLconf into account

I'm working through the Django 1.4 tutorial, and I notice that in the view layer, URLs are assembled by hand:
<form action="/polls/{{ poll.id }}/vote/" method="post">
And so on.
However, on the controller side, URLs are generated dynamically:
return HttpResponseRedirect(reverse('polls.views.results', args=(p.id,)))
Something seems a little inconsistent about this. Since the prefix for the URL (/polls in this case) is determined in the project's URLconf instead of the application's URLconf, it seems unwise to hard-code this value in the template.
Is there a helper or some other way to generate a URL in a Django template so that it takes the URLconf into account?
Yes, you can use the builtin url-tag to avoid hardcoding a path.
For example:
{% url 'myapp:view-name' %}

What is "load url from future" in Django

When I read django code sometimes, I see in some templates "load url from future". I am not quite sure what this is but I do know it has something to do with URLs. How and when is this load url from future supposed to be used?
It's due to a change to the url tag enacted in 1.3:
Changes to url and ssi
Most template tags will allow you to pass in either constants or variables as arguments – for example:
{% extends "base.html" %}
allows you to specify a base template as a constant, but if you have a context variable templ that contains the value base.html:
{% extends templ %}
is also legal.
However, due to an accident of history, the url and ssi are different. These tags use the second, quoteless syntax, but interpret the argument as a constant. This means it isn’t possible to use a context variable as the target of a url and ssi tag.
Django 1.3 marks the start of the process to correct this historical accident. Django 1.3 adds a new template library – future – that provides alternate implementations of the url and ssi template tags. This future library implement behavior that makes the handling of the first argument consistent with the handling of all other variables. So, an existing template that contains:
{% url sample %}
should be replaced with:
{% load url from future %}
{% url 'sample' %}
The tags implementing the old behavior have been deprecated, and in Django 1.5, the old behavior will be replaced with the new behavior. To ensure compatibility with future versions of Django, existing templates should be modified to use the new future libraries and syntax.
I will put this in a separate answer due to the following salient Exception in connection with templates:
If you get a django.core.urlresolvers.NoReverseMatch Exception thrown from within a django template (Django version >1.4) parser, it may just be the usage of {% load url from future %} within the template.
In this case, simply quote the url that is passed to the url-tag. That is {% url someurl %} should become {% url 'someurl' %}. Thanks to Ignacio VA for pointing me in that direction.

View referenced by two urls and url tag

I am using url tag in my template for a view, that is used by two different urls. I am getting the wrong url in one place. Is there any way to force django to retrieve different url? Why it doesn't notify my, that such conflict occured and it doesn't know what to do (since python zen says, that is should refuse temptation to guess).
Code in template:
{% url djangoldap.views.FilterEntriesResponse Entry=entry.path as filter_url %}
Code in urls:
(r'^filter_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'filter_entries.html',
'results_template': 'filter_results.html'}),
(r'^choose_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'search_entries.html',
'results_template': 'search_results.html'}),
As you can see, those two urls use the same view, but with different templates. How I can force django to retrieve former url, rather than latter?
Name your URLs by adding another item to the tuple:
(r'^choose_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'search_entries.html',
'results_template': 'search_results.html'},
'sensibleprefix-choose_entries') # <-- this is the name
Then you can use the name in the URL tag.