Pre-requisite: Basic knowledge of python.
Django is a python web framework that enables rapid development of secure and maintainable websites and is open source.
When a HTTPS request is received then application works out what is needed based on the URL and then as required the application may read or write information from database or perform any other task performed to satisfy the client request.
Pictorial representation of working of Django(Source :MDN Web Docs)
urls.py: Instead of defining all the routes/URL patters in a single function is possible but it is much more maintainable to define those patterns in a single file , in Django that file is called URLs.py . It basically helps in routing all the URL requests to specific views (discussed in later sections) to fulfill user requests. It consists of various patterns having strings , numbers , etc. in the URL and are passed to the view function as data as the URL may consist of special parameters that might help in fetching data for sending response to the client.
Views: Views in Django are request handler functions that receives HTTP request and returns HTTP response. Views access data through models to satisfy requests from clients.
Models : Models in Django can be simply defined as a database where the structure of application data is defined and it provides mechanisms to Create , Read , Update and Delete the data in the application for fulfilling the user request.
Templates : Templates are files (like HTML files) with placeholders that is populated by actual content. Views create dynamic HTML files using templates and populate it with data from models. A template can be used to define the structure of any file , not only HTML!
Routing Requests (urls.py)
So , when a request is received from the front-end then based on the URL it is routed to a specific view using urlmapper , it basically defines a set of URLs and the corresponding views to which the request will be routed to that specific view. All of this is stored in urls.py
Below is an example of how urls.py looks like:
urlpatterns = [
path('admin/', admin.site.urls),
path('book/<int:id>/', views.book_detail, name='book_detail'),
path('catalog/', include('catalog.urls')),
re_path(r'^([0-9]+)/$', views.best),
]
urlpatterns in the above example is a python list that consists of the path/re_path function , that basically takes two arguments. The first argument is a pattern (route) that will be matched , the pattern may consist of some other parameters that are passed in the URL and are then captured and sent to views for fetching some data . The second argument is also a function that is in a module called views (views.py) , where the function is stored . In the example above , for the path book/<int:id>/ the request is routed to the views module and a function called book_detail
Processing Requests(views.py)
Views.py is responsible for handling the HTTP response and sending back the HTTP request , in between views.py will interact with the database to manipulate/fetch the data and then send back the response to the client.
The example below shows a very simple example where the index() function in the views model is receiving HTTP request from some URL and been called by the URL mapper. It takes request object as parameter and returns response object , in this case it is returning a hard coded string.
# filename: views.py (Django view functions)
from django.http import HttpResponse
def index(request):
return HttpResponse('Hello from Sundaram!')
In the above example , first we import the HTTPResponse object from the Django.HTTP module to use it in the function.
Next , a function named index is defined that takes request(HTTP.Request) object as input parameter and then it returns a response , a hardcoded string in this case.
Working with Data in Django
Django web applications query data through models that are defined in models.py file. The models basically define the structure of stored data , their maximum size , type of data that can be stored etc. Once you define the model and other part of the code , then you can use any database and all the inner communication is done internally by django
Let's see a sample of how a models.py looks like:
from django.db import models
class Team(models.Model):
team_name = models.CharField(max_length=40)
TEAM_LEVELS = (
('U09', 'Under 09s'),
('U10', 'Under 10s'),
('U11', 'Under 11s'),
)
team_level = models.CharField(max_length=3, choices=TEAM_LEVELS, default='U11')
Let's breakdown the above code and see what each line of code is doing:
- from django.db import models
Importing the models module from django that will provide functions to interact with the data.
- class Team(models.Model):
Defines a model named Team that inherits the base 'Model' class of Django
- team_name = models.CharField(max_length=40)
The Team model has a single field team_name of type character (CharField) with a maximum length of 40 characters.
TEAM_LEVELS = (
('U09', 'Under 09s'),
('U10', 'Under 10s'),
('U11', 'Under 11s'),
# …
# list other team levels
)
TEAM_LEVELS above is a tuple that basically is defining a list of choices for the team_level field . It contains two elements: one human readable format and the other that is stored in the database.
team_level = models.CharField(max_length=3, choices=TEAM_LEVELS, default='U11')
The above code snippet defines another firls called team_level of the type character (CharField) with maximum length of 3 characters. Another parameter is choices that basically defines the set of values that particular field can have , in this case the team_level field can have pre-defined set of values from the tuple TEAM_LEVELS defined above. Another field default gives a default value to that field , in this case the team_level field is assigned a value of U11.
Querying Data
Once you define the models , views now we need to work on querying/ fetching that data . For this Django provides a simple query API that helps in searching the associated databases and can match against a number of fields based on different criteria like case-insensitive , exact match , etc.
Let us look at an example below:
from django.shortcuts import render
def index(request):
list_teams = Team.objects.filter(team_level__exact="U09")
context = {'youngest_teams': list_teams}
return render(request, '/best/index.html', context)
The first line imports the render() function from django.shortcuts module that is used to render the HTTPResponse for the incoming request.
The second line defines the index function to handle the incoming request .
The third line queries the database using the Django model Team It retrieves a list of teams where the team_level field is exactly equal to "U09". The double underscore (
__
) is used in Django queries for field lookups.Then we define a variable called contexts , this variable basically defines the data that is to be passed down the HTML Template for rendering it to the response. In this case the list_teams will be passed down to the HTML template and will be rendered in the response page. The youngest_teams variable is used as a reference in the HTML template.
Then , we are finally returning the response using the render() function imported above. The render() function accepts 2 arguments: The incoming request , the path to the template that will be sent as a response and the context variable that contains the data that will be passed down the template to be rendered in the HTTPResponse.
Rendering Response
Below we will see how the data is rendered through the HTML template:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Home page</title>
</head>
<body>
{% if youngest_teams %}
<ul>
{% for team in youngest_teams %}
<li>{{ team.team_name }}</li>
{% endfor %}
</ul>
{% else %}
<p>No teams are available.</p>
{% endif %}
</body>
</html>
In the above section we saw the file path '/best/index.html' , the above script is index.html , it consists of everything that will be rendered as the response to the request.
In the above script first it is checked if a variable named youngest_teams exists , if it does then it iterates over each value in youngest_teams using for loop and then each team name is rendered in the form of list.
Conclusion:
This blog covered how the internal communication in Django web applications is carried out among the various directories in order to serve an incoming request by routing the request to the intended handler , fetching or updating the data in the database and then rendering the data in the database.
In the later blogs we will see some more advanced concepts.
Happy Coding fellow devs! :)