Building an API for website on Django by using REST framework
24.02.2025
24.02.2025
8 minutes
70
1
0
0
0
Introduction
Good day. Using my SearchResultParser project as an example, I will show you how you can make an API for your site and how this API can be used from the client side. I am writing the backend in Django, and the Django REST framework will be responsible for creating and configuring its API.
The process of creating a Django REST API for a website can be described in the following steps:
- Create a project and pre-install all the necessary packages, configure it
- Create models that we want to use on the client side
- Create serializers for them.
- Create views (handlers) for them
- Connect routers and paths
- Write and configure a client to work with the developed API
For objective reasons, I will skip the 1st step. Because the SRP project has already been created and configured, you can see how to configure it and bring it into life, and in the meantime I will describe the next steps.
I will also add that you will need to install and connect the following python modules:
- django-cors-headers: to activate the so-called Cross-Origin Resource Sharing (CORS) for communication between the React application and the Django API.
- djangorestframework: this is a Django application that allows us to easily build an API for our site.
- django: the backend of our site, database management
That's it, connect the newly installed modules in settings.py:
Also, please note that I have a separate Backend application. My entire API will be there. It also needs to be connected, because that's where we'll be writing everything.
Setting up REST API for Django, creating models
So, now my site SearchResultPaser has a system for parsing data from search engines. At the time of writing this article, only Google. Plus the ability to add new search engines and delete old ones. But this site is not limited to this.
I should also have so-called presets, that is, in Django language, the Preset model, which will be available to each registered user to save and customize their favorite search queries.
Here is the full code of the model, using this example we will be working on serialization:
As you can see, this model has a ManyToMany relationship (One record in the Preset table can be linked to many records in the DB of Query models) with the Query model. Query is a wrapper for storing user queries. I want to draw attention to the fact that I will only save those queries that are necessary for the preset. In general, there is nothing special in this model. Let's look at the Query model:
It is even simpler, there is a text field query and a ForeignKey connection with the following model SearchEngine (One record in the Query table can have a connection with only one record of the SearchEngine model).
And of course the SearchEngine model:
Each entry of this model has a current state. Ready - means that the user can select it on the site and get the corresponding SERP results. InDevelopment - means that the corresponding parser has not yet been written and cannot be used now. And the last status, NeedsSetup, means that the user can use this parser, as in the first case, but it requires preliminary configuration in the user profile.
I also want to note the config field. Each search engine is unique when trying to parse it through the official API. In any case, only I can either add or delete entries to the SearchEngine table.
Setting up REST API for Django, creating serializers
To be able to work with these models on the client side (via JS), we will need Serializers. To do this, import the serializers module from rest_framework and write what we want to serialize:
There is nothing special about these serializers. We create a class through inheritance. Then we select the model and fields that we want to serialize. Moving on.
Setting up a REST API for Django, creating special views
Now, we would like to see what we are adding, deleting or changing. We need to create views in the Backend/views.py file:
Let's go through each of them. PresetModelView, its feature is that we filter all our presets depending on the user who wants to receive them. The feature of SearchEngineModelView is that it can only be viewed, but you cannot add or delete records from the database.
Setting up the REST API for Django, connecting views
And the final touch. To finally see the REST API in action, you need to connect the previously created view classes: QueryModelViews, SearchEngineModelViews and PresetModelView. To do this, connect a new router in the Backend/urls.py file:
That's it, done. Let's see what we got. Go to localhost:8000/api/ you'll see something like this:

As you can see in the picture, we have successfully connected and configured our router. Let's go to any of the links provided, for example localhost:8000/api/se/

Or, for example, let's look at the presets page, which is what this whole thing was all about. So, I have two accounts, dima and some, and each has its own presets. Let's see how filtering by user works:

User some

User dima
As you can see, the first user has only one preset with id=3. And the second has 2 presets with id=1 and 2.
Additional Django REST framework setup
You probably have a question that all this is beautiful, but you just want to get a JSON file on the client side and do what you should. I was itching too, and I found a pretty elegant solution to this problem.
Look, in development mode we will be shown previous pages in pictures, but if we change the mode (i.e. make debug=False in settings.py) we will get responses like this:

To achieve this result, simply add the following lines to the end of the settings.py file:
We just change the default renderer and what we get is... a JSON file.
Working with the API from the client side
Working with the API from the client side is very simple. You need to make the appropriate AJAX request and process the response. For example, this is how I will get all available records in the SearchEngine model:
For example, I want to add different status icons for each search engine. To get direct data from the response, we will access a special data object in the response and then the fields we need. And depending on the engine status, we will either add a handler to it or not.
Yes, I realize this code block is much more complex, with nested AJAX requests. But this example is perfect for demonstrating how to get data from a response.
And here are the responses from the server:

For localhost:8000/api/se/

For localhost:8000/api/seue/
And how it might look on the website:

Conclusion
So, we have finished setting up our site's API using the Django REST framework. Of course, at first it may seem that all this is somehow confusing and too complicated, but believe me, when your project becomes a little more complicated than a one-page landing page, you will immediately remember about the Django REST framework and that it is not so hard to learn ( •̀ ω •́ )y
Comments
(0)
Send
It's empty now. Be the first (o゚v゚)ノ
Other
Used termins
- Axios library ⟶ It is a promise-based HTTP Client for node.js and the browser. It is isomorphic (= it can run in the browser and nodejs with the same codebase). On the server-side it uses the native node.js http module, while on the client (browser) it uses XMLHttpRequests.
- CORS (Cross-Origin Resource Sharing) ⟶ Is a security feature implemented in web browsers that enables controlled access to resources located outside of a given origin (domain, protocol, and port combination). It is a mechanism that allows web servers to specify who can access their resources and which HTTP methods are permitted for cross-origin requests.
Related questions
- What is the difference between OneToOne and ForeignKey fields ? Their main and fundamental difference is how they relate to the model they refer to. If the relationship between the model with the OneToOne field and the target model is such that there can only be one such record in the database, then ForeignKey allows an unlimited number of such records.
- When to use OneToOne model field in Django ? This model field is perfect when it is necessary to add new functionality to an existing model (or rather, to a model entry in the DB). That is, when changing the existing functionality of already created models is not justified as it is difficult or expensive.