38

I have this anchor link:

<a href="/question/tag/1/1/?list_id={{title}}">{{title}}</a>

Sometimes, this title has some content with + (add operator) like: "Django + Python"

But when it is directly placed on anchor links, the url delivered will be:

http://127.0.0.1:8080/question/tag/1/1/?list_id=Django + Python

Which will eventually cause problem on the retrieval as the url decoder thought the list_id GET = DjangoPython.

So, does anyone knows how to avoid this issue? Note that I do not want to change anchor links to input buttons.

jdtoh
  • 1,697
  • 2
  • 13
  • 18

2 Answers2

97

Instead of

{{ title }}

do

{{title|urlencode}}
jdtoh
  • 1,697
  • 2
  • 13
  • 18
-2

Instead of hardcoding the URL and building the querystring in the template by concatenating the title context item, consider simplifying it a bit by using django.core.urlresolvers.reverse() and specifying a named URL from the relevant urls.py file. Makes for a clean design when you don't have to worry about URLs changing! Imagine the headache of all the scattered HREFs you'd have to change, versus simply assigning a context variable from the view set to the result of the reverse call. The querystring can be added nicely in the view too, without having to worry about some of the often strange template parsing rules. Note that the urllib.urlencode function acts completely differently to the template filter of the same name; don't get confused! It can be used as follows:

# If the entry in URLConf has named capture groups such as ?<pk>,
# pass a dict as kwargs parameter instead.
url = reverse('your-named-url', args=(1, 1))  # e.g '/question/tag/1/1/'
# Encodes as form data to 'list_id=Django+%2B+Python'
querystring = urllib.urlencode({'list_id': 'Django + Python'})
context['question_url'] = '{}?{}'.format(url, querystring)

Then, in the template it can be as simple as href="{{ question_url }}". It might seem like more work, but it can pay off very quickly and it's a much better separation of concerns. Normally I'd use the {% url "your-named-url" %} template tag, but it doesn't currently handle querystrings nicely -- as in, not in the same manner as it deals with URL args and kwargs defined in URLConf.

trojjer
  • 629
  • 7
  • 10
  • This reply doesn't answer the question, and usefulness of the recommendation is doubtful: hiding URL structure in a context variable is not always a good idea. – David Avsajanishvili Mar 28 '17 at 13:53
  • I think @jdtohs answer accomplishes all that this answer tries to do - ie it uses a variable in the template, and then a template filter to encode the string. In marking down, i was really trying to get the other answer to move above this one! – stephendwolff Aug 01 '17 at 10:39