Reputation: 38153
URLConf:
url(r'^body/(?P<id>\d+)/$', 'body_part_detail', name='body-part-detail'),
url(r'^body/(?P<id>\d+)/(?P<slug>[-\w\d]+)/$', 'body_part_detail', name='body-part-detail'),
get_absolute_url()
implementation:
def get_absolute_url(self):
kwargs = {
'id' : self.id,
'slug' : slugify(self.name)
}
return reverse('body-part-detail', kwargs=kwargs)
Now, I've got two url
s where name=body-part-detail
(which may be wrong?). Nevertheless, reverse
succeeds in the sense that it uses the second url
and returns the desired URL with the slug component. Why does this work? Am I just "lucky" in this case (quotes because programs shouldn't be lucky!)?
Finally, there are several places on SO and the Web where people give examples of URLConfs with url
s that share name
keyword arg. For example, Visgean Skeloru's answer here: Optional get parameters in django?. Is this wrong/bad?
Upvotes: 2
Views: 153
Reputation: 13328
The reverse
function is identifying that you have the kwargs id
and slug
along with a pattern name body-part-detail
, and returning the only url that corresponds to those kwargs and that name. You're not lucky, that's what reverse
is designed to do.
You may be able to use the same name for numerous patterns but I don't think that's how it was designed to work (I can see a very old bug ticket that suggested implementing a check to ensure there aren't any duplicates). I suspect that your app will be easier to maintain if you use a unique name for each pattern. Have a look at the docs for me more info.
Upvotes: 4
Reputation: 122436
In your reverse()
call you're passing two arguments. So Django discovers that it can't match it to the first URL because, although the name is correct, that URL only has one URL parameter. So Django necessarily matches it to the second URL.
Optional URL patterns are okay but it's best to give each URL a unique name and use that to reverse URLs. That removes any ambiguity when resolving URLs and it also makes the code easier to follow for yourself and other developers.
Upvotes: 3