The only thing different from my other url tags is that this one has a literal string in it. None of the various web discussions about literals in urls were useful (and don’t get me started on the ridiculous ‘load from future’ tag). So my hack fix to this is to pass in the word “exhibitions” through the context param. Irritating.
That would be a valid use of a url defined that way.
However, I’d look at it from the other direction.
Why are you passing 'exhibitions' as a second parameter?
Side note: Your error also shows that you don’t have a value for space.name in the context being used to render this template. You need to ensure that your tag is referencing the proper variable.
Aha… I wasn’t understanding the function of the pattern name — that’s why I putting ‘exhibitions’ in the path, for disambiguation. So now I have this, which works:
That’s fine to have the string ‘exhibitions’ in the path. Using:
Is 100% valid and correct.
However, in both cases (with and without ‘exhibitions’), there’s only one parameter.
You would properly render this url with: {% url 'exhibition_list' space.name %}
The problem with your previous attempt was with trying to use that path with: {% url 'exhibition_list' space.name 'exhibitions' %}
If you’re populating space_name in the context, that’s the wrong context variable, because you’re specifying space.name as the parameter, which would be the name attribute of an object or dict named space.
The path takes precedence. Django uses the first matching entry in your URLconf, the path name (or rather view name) is mostly only used for reversing URLs.
The name parameter is an empty string. That’s no good. I would guess there’s a template error being swallowed. I recommend installing django-fastdev which turns these errors into hard errors in the template where the error is.
It is a definitive identifier within Django. When you are reversing a URL, you are creating a url based upon the name given.
However, the names are meaningless for URLs being requested. Your browser doesn’t submit a name, it submits a url. The url being submitted is compared to each of the defined paths in the order that they are defined, and will call the first view where the url matches the path.
I have to say, though Django’s documentation is generally very good, for this feature it’s rather poor (of course, it’s hard to write good documentation of a badly-designed scheme — but I digress).
I, controversially, tell people not to use reverse()/{%url%} and just write out the url. It’s error prone, and slow, and what do you get for that work? It becomes easier to change urls later, which is so rare that it doesn’t matter.
(For library authors you need it though, and for i18n urls)
There’s another situation where it’s important too, and that’s the case where you’re needing to deploy multiple projects, or multiple instances of the same project on one site, and you need to segregate those projects below different base URLs.
In our situation, that’s far from being “so rare that it doesn’t matter”.
As a side note, we also find that using it reduces errors in that fewer mistakes are made by being able to reference a single app:name for a long url and passing parameters by name rather than needing to remember that full path and the order in which parameters are being provided.
As long as you use reverse() then sure. It’s just that the combination of template silent errors creating empty strings and then failing silently after that that is a problem.
It’s also an issue of the above, plus the poor error message (it could list all valid names for example!), that makes many beginners struggle needlessly imo. It’s just not worth it for people who are already struggling with basics like HTML, CSS, and Python.