Django, self-proclaimed as the framework for perfectionists with deadlines
, is a handy tool for many Python developers. Boasting features like great security, versatility, and scalability, Django is one of the go-to solutions for building your next project with — and this claim is backed by millions of web developers choosing this very framework.
However, with such a great number of developers to choose from, how do we test their knowledge? We may need to hire a few remote Django developers now, then we might want to bring some of them on-site — so how should we go about building our recruitment strategy? Luckily, we can use guidelines like this for one of the most important stages of a remote web developer’s hiring process — technical interview. In this article, we cover the best questions you can ask a Django developer to test their knowledge.
1. What are the design philosophies of Django?
Being written in Python, Django utilizes Python’s design philosophies to make for more efficient programming workflow. These include:
- • Loose coupling: preventing different elements of the framework from being heavily dependent on each other, unless absolutely necessary
- • Less code: following the “Zen of Python”, using as little code as possible is encouraged, while boilerplate code should be avoided
- • Quick development: following its motto of “ …for perfectionists with deadlines”, Django should be used to develop the project and deploy it as fast as possible, eliminating any hassle a developer can experience
- • Explicit is better than implicit: infamous “magic” code should be avoided; instead, the code used in a Django project should be easily understandable.
2. What drawbacks of Django should we look out for?
Python and its frameworks are commonly thought to run somewhat slowly. By that proxy, shouldn’t Django’s performance be inferior to that of other solutions’?
Attributing the project’s performance and runtime speed solely to its framework is a misconception. Your project is a network of different services, all communicating with one another; therefore, factors like slow database queries and network latency should be considered as well. To remedy this, we can use Django’s own cache library together with Memcached.
For another layer of optimization, we can utilize Varnish — software that functions as an HTTP caching layer. With Varnish, we can group server requests into two groups: unique and not unique. Varnish then manages the un-unique requests, offloading their pressure from the server.
To sum it up, considering Django to be an outright slow framework would not be fair.
3. How can we use sessions?
The goal of using sessions in Django is to keep track of the ongoing communications between the website and the client: they allow Django developers to store data per browser and retrieve said data when needed. To identify the browser and its session, a special cookie file with session id
is used.
How can we access sessions? We can do it via the request
parameter; as the session attribute functions like a dictionary, we can use all dictionary-related commands like looping through data or clearing it.
Where is the actual session data stored? The default setting is storing it in the site database: this is more secure than storing the data in cookie files (which are more prone to be compromised). Other storing locations like cache or files can be used, although using the site database is the best practice security-wise.
4. What are signals?
A Django signal is a utility that the framework uses to execute a certain piece of code. Whether this piece of code should be executed is connected to a specific action or event that the framework detects: these can include registration of a new user or deletion of a data item.
Some of the signals are: pre_save
and post_save
; pre_delete
and post_delete
; pre_request
and post_request
.
5. Which caching strategies can we use?
Some of the caching strategies that can be used in Django are:
- • File system caching
- • In-memory caching
- • Using Memcached
- • Database caching
6. What is the difference between forms and model forms?
Although they are both used for creating form inputs via widgets and validating data from the browser, their difference lies in the way they interact with models:
- • Forms are manually configured by the developer and used when they do not have to interact with the model and the collected data has no relation to it. Use cases may include a contact/newsletter subscription form.
- • Model forms, on the other hand, are generated automatically (and can be later configured by the developer) and require that the collected form data has close relations with the model. Use cases may include forms that need to interact with the database.
7. Can we use Object-Relational Mapping in all scenarios?
No, in certain use cases ORMs are suboptimal: the rule of thumb is to determine whether the data set is going to be complex (i.e. consisting of multiple joins and nodes) — if it is, SQL will have superior performance and be overall more convenient to work with.
8. How are user requests processed?
The user’s request is processed at the following stages:
- Django decides which of the root URLconf modules it should use; by default, this is equal to the value of the root_urlconf setting. However, should the incoming HttpRequest object have an attribute of urlconf (assigned to it by middleware), Django will them use this instead of the root_urlconf setting.
- The module that Django determined to use is loaded; then the variable urlpatterns is searched for — this variable should be a Python list of django.urls.path() and/or django.urls.re_path() instances.
- Django loops through every URL pattern and stops once a matching URL is detected.
- Django imports and calls the given view, which is a simple Python function (or a class-based view). The view gets passed the following arguments: It then imports and calls the given view and passes a number of arguments to it: a) a HttpRequest instance; b) matches from the regular expression (in case no named groups were found); c) keyword arguments.
9. How can we use model inheritance?
Django’s object-oriented models can be easily mapped to database table structures, creating inheritance properties that they will be sharing. That way, the inheriting model will not interfere with the base one. It is common for a web project to include multiple models; to showcase inheritance, we can use a base model (which we can name “content” and have it store general description values related to it: title, description, dates of creation and/or modification, etc.) together with another model (that we can name “audio”). The “audio” model will inherit the properties of the base model “content”, while also utilizing its own: source, link, embed code.
Having created the base model, we let Django map it to a table named projectname_content (where “projectname” refers to, well, your project’s name) — and makes it inherit from model.Model. We then create the “audio” model but make it inherit from “content” instead of model.Model. The convenience of this method comes from the fact that Django manages the inheritance systems autonomously, creating two tables: projectname_content and projectname_audio respectively. This relation can also be accessed via SQL methods.
10. How can we compare Node.js and Django?
What would you say about another backend solution, Node.js, and how it compares with Django?
It heavily depends on the priorities you set in your project. The most common criteria are: database type (e.g. Django for a relational one), security (Django offers great security), rapid development (also Django). Other criteria may include: better performance (Node.js is more fitting), creating features from the ground up (also Node.js) or better client-side processing (Node.js).
A distinctive caveat of Node.js lies in its asynchronous elements: they require the developer to be ever so vigilant because code errors may not reveal themselves until late in production.
11. How can we optimize a Django project’s performance?
Although it depends on the databases and models used in the project, there are some methods that always prove to be effective:
- • Analyzing the runtime of functions via the
line_profiler
module. Sometimes we may notice that the code runs slowly — and we need to examine our functions line-by-line. Using theIPython
debugger with theline_profiler
module, we can see exactly how much time each function takes to execute — and then we optimize the code, if needed. - • SQL logging. To dissect a function suspected of low performance even further, we can utilize SQL logging, getting a list of every SQL query that gets executed. It is important to limit this type of logging to a single function — otherwise, the printout would simply flood us with information.
Although a technical interview may seem like a challenging task, conducting it correctly and asking the right questions will net you the best remote web developer you can hire!
A good hiring strategy is synonymous with knowledgeable HR managers — so every time you share our article, our whole industry becomes better and better! 🙂