Why django urls end with a slash?
Question:
Django official documentation and other tutorials on the web always use a trailing slash at the end of url. ex:
url(r'^accounts/login/', views.login) # login view in turn calls login.html
# instead of
url(r'^accounts/login', views.login)
Since accounts
is the directory and login (login.html)
is the file, shouldn’t we be using second url? This will also make GET
parameters look more structured:
accounts/login?name='abc' # login is a file that is accepting parameters
vs.
accounts/login/?name='abc' # login directory (maybe index) is accepting parameters??
Answers:
This helps define the structure of your website. Although django can support anything entered after the domain that is passed to the server doing it in this way allows you to easily add “subpages” to the url without it looking like accounts/loginreset?id=alkfjahgouasfjvn25jk1k25
That being said in the case above it may make sense to leave it out.
From the docs for the middleware that uses APPEND_SLASH
a search-engine indexer would treat them as separate URLs – so it’s best practice to normalize URLs.
Its not required by django, its just trying to help your SEO by suggesting a standard way of doing urls.
Yes, I know that the slash has nothing to do with this middleware but this is the best explanation I could find as to a possible reason
One of Django’s core design philosophies is URLs should be beautiful.
So some url like accounts/detail?name='abc'
should be mapped as accounts/detail/abc/
. You can capture it using regex at your url configurations. Here the URL is pretty neat and user friendly. This will help the search engines to index your pages correctly (now you can forget about rel=canonical
) and will help in seo.
Now the reason for a trailing slash, consider a view (in any framework) which relatively resolves about.html
for a user at path, users/awesomeUser
since users/awesomeUser
and users/awesomeUser/
are different,
-
If the user is at users/awesomeUser
, the browser will resolve it as users/about.html
because there ain’t a trailing slash which we don’t want
-
If the user is at users/awesomeUser/
, the browser will resolve it as users/awesomeUser/about.html
because there is a trailing slash
child
relative to family/parent/
is family/parent/child
.
child
relative to family/parent
is family/child
.
Django Design philosophy on Definitive URLs reads,
Technically, foo.com/bar and foo.com/bar/ are two different URLs, and search-engine robots (and some Web traffic-analyzing tools) would treat them as separate pages. Django should make an effort to “normalize” URLs so that search-engine robots don’t get confused.
This is the reasoning behind the APPEND_SLASH setting. (APPEND_SLASH lets you force append slashes to a URL)
Still not convinced?
- Since django observes both the urls as different, if you are caching your app, Django will keep two copies for same page at
user/awesomeUser
and user/awesomeUser/
.
- You gotta have issues with HTTP methods other than GET if you don’t append slash to a URL (If you ever plan to build a REST API).
Update
You can’t make POST/PUT/PATCH/DELETE methods to work with rest_framework
unless you explicitly define APPEND_SLASH=False
in settings and trailing_slash=False
for each and every router you gotta use(if you use Routers). It is like you basically gonna skip this most times and you gotta waste a hell lot of time debugging this. Django recommends append slashes
and doesn’t force it.
Its up to the developer to append slashes or not.
“URLs should be beautiful”!!!
I want to be able to control URLs. It’s nothing nice when everything is about to be overwritten. Under circumstances, I make a redirect loop which is not funny.
from django.http import HttpResponseRedirect as rdrct
url(r'^sitemap.xml$', 'my_app.views.custom_sm'),
url(r'^sitemap.xml/$', lambda x: rdrct('/sitemap.xml')),
Django official documentation and other tutorials on the web always use a trailing slash at the end of url. ex:
url(r'^accounts/login/', views.login) # login view in turn calls login.html
# instead of
url(r'^accounts/login', views.login)
Since accounts
is the directory and login (login.html)
is the file, shouldn’t we be using second url? This will also make GET
parameters look more structured:
accounts/login?name='abc' # login is a file that is accepting parameters
vs.
accounts/login/?name='abc' # login directory (maybe index) is accepting parameters??
This helps define the structure of your website. Although django can support anything entered after the domain that is passed to the server doing it in this way allows you to easily add “subpages” to the url without it looking like accounts/loginreset?id=alkfjahgouasfjvn25jk1k25
That being said in the case above it may make sense to leave it out.
From the docs for the middleware that uses APPEND_SLASH
a search-engine indexer would treat them as separate URLs – so it’s best practice to normalize URLs.
Its not required by django, its just trying to help your SEO by suggesting a standard way of doing urls.
Yes, I know that the slash has nothing to do with this middleware but this is the best explanation I could find as to a possible reason
One of Django’s core design philosophies is URLs should be beautiful.
So some url like accounts/detail?name='abc'
should be mapped as accounts/detail/abc/
. You can capture it using regex at your url configurations. Here the URL is pretty neat and user friendly. This will help the search engines to index your pages correctly (now you can forget about rel=canonical
) and will help in seo.
Now the reason for a trailing slash, consider a view (in any framework) which relatively resolves about.html
for a user at path, users/awesomeUser
since users/awesomeUser
and users/awesomeUser/
are different,
-
If the user is at
users/awesomeUser
, the browser will resolve it asusers/about.html
because there ain’t a trailing slash which we don’t want -
If the user is at
users/awesomeUser/
, the browser will resolve it asusers/awesomeUser/about.html
because there is a trailing slash
child
relative tofamily/parent/
isfamily/parent/child
.child
relative tofamily/parent
isfamily/child
.
Django Design philosophy on Definitive URLs reads,
Technically, foo.com/bar and foo.com/bar/ are two different URLs, and search-engine robots (and some Web traffic-analyzing tools) would treat them as separate pages. Django should make an effort to “normalize” URLs so that search-engine robots don’t get confused.
This is the reasoning behind the APPEND_SLASH setting. (APPEND_SLASH lets you force append slashes to a URL)
Still not convinced?
- Since django observes both the urls as different, if you are caching your app, Django will keep two copies for same page at
user/awesomeUser
anduser/awesomeUser/
. - You gotta have issues with HTTP methods other than GET if you don’t append slash to a URL (If you ever plan to build a REST API).
Update
You can’t make POST/PUT/PATCH/DELETE methods to work with rest_framework
unless you explicitly define APPEND_SLASH=False
in settings and trailing_slash=False
for each and every router you gotta use(if you use Routers). It is like you basically gonna skip this most times and you gotta waste a hell lot of time debugging this. Django recommends append slashes
and doesn’t force it.
Its up to the developer to append slashes or not.
“URLs should be beautiful”!!!
I want to be able to control URLs. It’s nothing nice when everything is about to be overwritten. Under circumstances, I make a redirect loop which is not funny.
from django.http import HttpResponseRedirect as rdrct
url(r'^sitemap.xml$', 'my_app.views.custom_sm'),
url(r'^sitemap.xml/$', lambda x: rdrct('/sitemap.xml')),