URL designing and URL kwargs in Django

Subscribe to my newsletter and never miss my upcoming articles

A clean URL is really important for a good quality web application. You can design your own URL style i.e url can contain / or - anything there is no any restriction but these are the things i follow (some examples),

  1. /profile/<username>/ instead of /profile/<db_primary_key_id>/ to view user profile
  2. /hello-world/ instead of /helloworld/
  3. /accounts/change-password/ instead of /profile/<username>/account/settings/change-password/ for accounts password change
  4. /blogs/?page=1 instead of /blogs/page-1/ for paginations.

You can follow any pattern, but make it readable and consistent in your project

To create a URL on Django you simple create a path and point that path to a view function like we did in previous turorials. Here are some examples,

from django.urls import path

from profile.views import profile_view
from accounts.views import change_password_view

urlpatterns = [
    path('/profile/', profile_view),
    path('/accounts/change-password/',change_password_view)
]

As you can see we use path() function to create our URLs. The path function take arguments where we define the path of url and the view function that it points.

Capturing Values from URL

Let's assume a URL path /profile/<username>/ here <username> part is dynamic and we need to capture this value on our URL and pass it to the view function. For this purpose we use Path Converters. Django already provides us some path converters in default, they are: str int slug uuid path. A/c to the type we need, we can select a path converter and add it to the URL like below,

# urls.py
from django.urls import path

from profile.views import user_profile_detail_view

urlpatterns = [
    path('/profile/<str:username>/', user_profile_detail_view) # we used <str> path converter and assigned the value to username
]

since we need to grab the captured username on our view function as well, we can write our view function as,

# profile/views.py

def user_profile_detail_view(request, username):  # we added username argument on our view function
    # print(type(username)) # do this for every path converters to see tha magic. i.e: using <int> converter would give you <int> type
    # get this username info from DB
    # prepare output
    # send output as HttpResponse
    ....

We can always create our own custom path converters if the default converters do not satisfy our need.

Using regular expressions in URLs

Sometime we may need to use regular expression in our URL since everytime the simple path() wont satisfy our need. To create regular expression on url path use re_path() instead of path()

from django.urls import path, re_path

from blog.views import all_blogs_for_year_view

urlpatterns = [
    re_path(r'^blogs/(?P<year>[0-9]{4})/$', all_blogs_for_year_view),
]
How does URLconf work

Django consist of ROOT_URLCONF settings on your projects settings.py file. This is the one and only URL config file your django will look for. All urls in our project must be inside the defined ROOT_URLCONF file. You might come up with a question, There can be as many django apps in the project and they cna have their own urls, but if django can only look into the ROOT_URLCONF file, then how does our logic fit up. The answer is, you can have n numbers of URL files in your project, but through some way you need to integrate those urls on your ROOT_URLCONF file.

If incoming Request Object has urlconf attribute set (this can be from middlewares), then django will use this instead of ROOT_URLCONF, but dont worry about it for now.

Remember these things,

  1. in request http://127.0.0.1:8000/profile/, Django will look only /profile/ in your URL configurations file
  2. In request http://127.0.0.1:8000/profile/?id=123, Django will only /profile/ in your URL configrations file
  3. It doesn't look at the request method as well, All request methods. like HEAD POST GET will land to the same view function. You can from some way find the request method on your view function and perform the logic accordingly. i.e: post method on /profile/ will update your profile but get on /profile/ will display your profile information. We will look into this in later tutorials
Including other URLconfs

As our project grows up, we split our url files or group them for readability.

from django.urls import include, path
from profile.views import self_profile_view

extra_extra_url_patterns = [
    path("/me/",self_profile_view)
]

urlpatterns = [ # this is our main urlpattern list

    path("/profile/",include(extra_extra_url_patterns)) # include the patterns

    # this will create url ==> /profile/ + /me/ from extra_extra_url_patterns = /profile/me/ is the final URL created

    # and you can also include, other urls.py file from your app 
    path("world/",include('world.urls')) 
    # you do not need to import world.urls as you can simply write the dotted path of your url file
    # so, this means, inside your world app, there will be  urls.py file : world/urls.py
]

No Comments Yet