Developing A Backend Electronic Library API with Django
Modern API-driven development plays an important role to drive the Full Stack implementation of modern software applications across both back-ends and front-ends development teams. The word API represents Application Programming Interface.
In this tutorial, we are going to build an MVP (Minimum Viable Product) back-end API for a library management system using Python's Django framework. In this way “separation of concerns” between the back-end and front-end teams, which is such an important practice in today's software development industry is embraced.
The Back-end Django API so-developed can be ported to work with various cross-platform systems/apps on different environments such as desktop, mobile, and web across the internet/network. The project assets for this tutorial will be kept in a public git-based repository that will be mentioned later.
The Back-end API will fulfill the following Requirements:
1. Admin and normal users' accounts
2. Resourceful ebooks, categories, and reviews API with create, read, update, delete, and listing functionalities(CRUDL)
3. User authentication, authorization and registration
4. Ebook model with the following attributes; title, author/s, category, cover-image, and pdf file
5. Category model with the following attributes: name, description Plus Review model with user, rating, and comments attributes
Procedures in Brief
For clarity, this tutorial will explain step-by-step processes that are to be done to achieve the project goals by dividing the whole process into about nine parts. With the exceptions of parts 1 and 2, each of the other parts will be covering an important collection of subprocesses which collectively will be contributing to attaining the end goal by forming the critical milestone and hence be part of our git-based repository’s commits. Furthermore, there will be some interludes either within or between those nine major parts.
Part1 Preliminary steps
In this part we will prepare our development environment for enabling the Django project to get underway by first; installing various software which includes; python language interpreter, pipenv(one of the favorite Python’s virtual environment managers), git(version control tool) and secondly prepare the project directory within our Linux/ubuntu machine home folder.
1.1. Python installation: There are several ways to get a Python interpreter installation for your computer. One such option is to visit https://www.python.org/downloads the site contains downloads for varieties of Operating Systems and various interpreter versions up to the very latest ready-made releases.
1.2. Pipenv installation: Pipenv is both a dependency and package manager for Python packages. To install pipenv(which is a highly recommended virtual environment provision solution by the official Python packages index site or Pypi.org) open the command terminal and run the following highlighted command pip3 install pipenv
2. Git installation: For git installation in your local development machine check out the guide from the following site: https://gitscm.com/book/en/v2/Getting-Started-Installing-Git
3. Open the command terminal and change the directory to the home directory by typing the following command and then pressing the Enter button
cd ~
4. Create the projects folder and change the path to it by running the command highlighted below
mkdir projects && cd $_
- Create the library_api directory and switch paths to it by running the command highlighted below
mkdir library_api && cd $_
The below diagram shows how this goes from my laptop.
Part2 Project Creation
In this part we will look at how to create a Django Project, add apps to the Django project, and how we can interact with the Django starter app by spinning the Django server that comes with each Django installation in the development mode.
6. Before installing any package make sure that your development machine has a good internet connection. Run the following command from within the library_api folder path(project root folder) to install the Django framework into it.
pipenv install django |
If the above command runs successfully the Django is already installed and that can be seen as shown in the diagram below
7. To activate the virtual environment we run the following command from our project root directory which is the library-API directory’s path
pipenv shell |
If everything is okay the above command will provide us with the activated virtual environment as shown in the picture below.
Now run the following bunch of commands in the same order of succession to effect the creation of our API.
8.django-admin startproject library_api .
- python manage.py startapp ebook
10.python manage.py startapp user
The above commands do not run verbosely unless something wrong interferes so expect them to run quietly as can be seen in the diagram below
Interlude
After a series of operational steps done so far let’s perform the following activities which help us continue to pursue further achievements and reflect on the development efforts done so far. The activities include:
Installation of django-environ and pillow packages
Spinning up the development server
Visiting the localhost
Viewing the project folder structure
Open the command terminal and run the command shown below under the project’s root folder path
pipenv install django-environ pillow |
If somebody asks why “pillow”, pillow is the python package used to manage multimedia/image file manipulations and since we will have images for eBooks cover pages in our models, pillow is crucial for the proper functioning of the imagefield within our models.
On another hand, django-environ is an important package in effecting the interaction of settings.py file with the .env file which holds some secret credentials which are normally kept out of the public repository as a security enforcement strategy.
Run the highlighted command below from the same project’s root folder path to spin up the development server.
python manage.py runserver
Turn on your favorite browser and head on to http://127.0.0.1:8000/
The appearance of the above view in the browser is self-explanatory which indicates we are on the right track, if you miss that there might be another service running on that port 8000.
To view the Project Folder structure
Run the following command from the project’s root folder to visualize the project architecture
tree |
Please do not be flabbergasted by the seemingly large collections of files that appear in about five folders as I can assure you that for this backend api development project, we are hardly going to touch about 10 file types which are views.py, urls.py, models.py, settings.py, admin.py plus serializers.py, permissions.py and some few others common to several programming stacks like README.md .gitignore, .env etc. If you would like to learn more about the files not covered in this tutorial and Django in general I will advise you to read several titles at your own time at the end of this tutorial.
Part3 Adding in Project Basics’ artifacts
In this part, we will take a glance at how to add models’ data structure to the models.py file, edit the settings.py file, adding the .env, .gitignore, and README.md files which are of much relevance when it comes to working with git-based repositories.
11. Open the user/models.py file from the command line under the project’s root path by executing the following command
Nota bene, the command below assumes there is a working installation of visual studio code Integrated Development Environment(IDE) In your computer if you are using another type of editor please be guided accordingly on how to invoke it to open the specified file from the command terminal.
code user/models.py |
12. Edit user/models.py and add a User model that extends django.contrib.auth.models’ AbstractUsermodel
So that it appears as shown in the below diagram
12.B. Edit user/admin.py so that it appears as shown below
from django.contrib import admin |
- A. Open the library_api/settings.py file by running the following highlighted command next code libray_api/settings.py edit it by adding the bolded text below under the last line of the file AUTH_USER_MODEL='user.User’ as shown picture below
13.B. Edit the settings.py file add ‘user.apps.UserConfig’ to the INSTALLED_APPS array as shown in the following picture.
13.C. Open and edit the library_api/settings.py file by adding or editing all the items/lines with #NEW Comment shown in the next image as summarized in xxxxxxxxxxxxxxi and ii below.
i.Import environ, Initialize the environ
ii. Go to the SECRET_KEY and copy the string between the apostrophes to somewhere secure like the git untracked .env file and replace the SECRET_KEY=”xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx” with SECRET_KEY=env(“SECRET_KEY”) in this settings.py file as seen below.
14.A. From the project’s root folder path create the .gitignore, and README.md files by running the following command touch .gitignore README.md
14.B. Open the .gitignore file by running the highlighted command code .gitignore then edit it to add some files like .env etc
All the files and folder paths listed in the .gitignore file are not tracked/watched by git, this is the useful feature made in git to exclude some project files or folders from appearing in the git repo for various reasons like security, simplicity and other similar reasons.
15.A. Open the README.md file by running the command highlighted next code README.md then edit it to add some lines within it as shown below.
The README.md file is used for providing some project-related information to the members given access to the repository. Such info may include; app use summary/details, installation guide, licensing, and so forth.
15.B. Create both .env and .envExample files within the library_api folder. Mind you .env is exclusively yours as it is not going to be shared in the repository each developer member is advised to have his/her own and everyone will conclude all the parameters required in there by having a look at .envExample a reciprocal template copy of .env file. To create the following highlighted command
touch library_api/.env library_api/.envExample
15.C. Open the .envExample file by running the next highlighted command from the project’s root folder code library_api/.envExample then edit it to add a few (numbered)lines within it as shown in the next image.
15.D. Create superuser
As shown above, you will be required to supply a username, email, and password. If you come across any problem during the superuser creation process just type CTRL + C to quit and return to it again with much care.
16. Perform migrations by running the highlighted commands in A and B in the order
shown next.
A. python manage.py makemigrations
B.python manage.py migrate
17. From the project’s root folder run the following command
git init Note this is done only once per a given project’s root folder aiming at initializing the git repo
Interlude
With all the work done so far being right as we have learned above, it is high time to save the milestone reached as the git commit. We will be doing these types of commits at several points within this tutorial. The next three highlighted commands should be done under the project’s root folder even though the order for the first two is not strictly mandatory as it appears.
git add .
git status
git commit -m "Initial Commit"
Part4 Adding the models and building a working Admin Portal
In this part, we will add the app data models and build an Admin Interface or Portal to manage the data resources.
18. Open the ebooks/models.py file to add Ebook, Review, and Category models in it, by running the following command from within the project’s root folder code ebook/models.py
Add Categories as shown below
from django.db import models |
Just under the category model add the ebook model as shown below
Then add the Review model just under the Ebook model as shown below.
19. Open the library_api/settings.py file by running the following command code.library-api/settings.py then add 'ebook.apps.EbooksConfig' in the INSTALLED_APPS array
code ebook/admin.models.py then edit it so that it appears as shown below
21. Make migrations ebook and perform migrations by running the commands highlighted next in A and B
22. Start the Django local development server by running the highlighted command below python manage.py runserver then visit the localhost/admin(127.0.0.1/:8000/admin/)
and provide the credentials that were used during the createsuperuser process to log in and then interact with the user interface as illustrated below.
Admin Interface
Adding Category via Admin interface
Category added successfully
Adding an ebook
Adding a user named testuser by providing username, password, and password confirm particulars of the said testuser via the Admin interface
The user testuser added successfully after submitting the testuser’s particulars by hitting the save button.
Interlude
From the project’s root folder run the following command to update the repository. However, take note that even though I write git add . I have excluded the two multimedia files(.pdf, and png) that were added up during the Admin Panel Development so you should do the same by either adding those files types in the .gitignore list which is simply the best easy option or otherwise excluding them from commit changes as there are there simply as test cases to showcase how the whole puzzle fits together.
.git add .
git commit -m " Admin Panel Interface Ready"
Part5 Working Django rest framework
In this part, we will introduce the Django rest framework(Drf) which enables us to build restful web services applications which are commonly known as RESTful APIs. You may read more about REST at the next URL: https://restfulapi.net
- Run the next highlighted command from the project root folder to add djangorestframework
pipenv install djangorestframework |
24. Open the library_api/settings.py file by running the following highlighted command
code library-api/settings.py and edit it by firstly, adding ‘rest_framework’ to the INSTALLED_APPS Array and secondly, adding the REST_FRAMEWORK object below the middleware array with the default_permission_classes array in it just as it appears in the next image
25. Create the ebook/permissions.py and the ebook/serializers.py files by running the command highlighted below from the project’s root folder path
touch ebook/permissions.py ebook/serializers.py ebook/urls.py |
26. Open the bunch of files as shown in the highlighted command below from the project’s root folder to write or edit them to make them appear as shown in the images next to the command.
A.
code ebook/permissions.py ebook/serializers.py ebook/views.py ebook/urls.py library_api/urls.py |
User, ebook, and category serializers as part of serializers.py
Review serializer as part of serializers.py
CategoryViewSet, and EbookViewSet as part of the views.py file
ReviewViewSet, and UserViewSet as part of views.py file
ebook/urls.py file
library_api/urls.py
27. Different from other languages’ stacks Django ships with the browsable api feature which enables us to interact with the API via the browser instead of depending on other tools like Postman or Curl to do so.
A.python manage.py
B. migrate, python manage.py runserver
- Interacting with our API by visiting the next highlighted URL with browser 127.0.0.1:8000/api/v1/ adding ebooks, categories, and reviews at the end of this URL we get to see the following views.
API Categories
API Reviews
Nothing is available from the reviews its an array as it is empty, as can be noted in the above image.
Let us scroll the view to the bottom and add a single review for the Torrey Trust’s ebook
Let’s add a review by filling in the note and clicking the POST button as shown in the image below
Finally, our review has been created/added as shown below
28. Wind up this part by updating our local git repository with the latest changes and committing them by executing the next highlighted command in that order.
git add .
git commit -m "Django RestFramework Implemented"
Part6 Adding djangorestframework-simplejwt authentication into the mix
In this part, we will add the rest frameworksimplejwt package in our API. It is a very important addition as it provides us with the famously socalled JavaScript Web Token implementation in our API which is a highly recommended authentication methodology across the modern cross-platform apps. Next are the steps.
29. Install the djangorestframework-simplejwt by running the command highlighted below from the project’s root folder path
pipenv install djangorestframework-simplejwt |
30. Open the library_api/settings.py file by running the next highlighted command
code library_api/settings.py and edit it by firstly adding 'rest_framework_simplejwt', to the INSTALLED_APPS Array and secondly adding the ‘DEFAULT_AUTHENTICATION_CLASSES’ array within REST_FRAMEWORK object as shown in the following image.
31. Open the library_api/urls.py file by running the next highlighted command from the project’s root folder path code library_api/urls.py edit it so that it appears as shown in the following image.
32. Perform the migration by running the next highlighted command from the project’s root path
python manage.py migrate |
33. Spin up the django development server by running the next highlighted command from the project’s root folder path python manage.py runserver
34. Using your favorite browser visit 127.0.0.1:8000/ and the added urls as shown next
Obtain a Token
At last, we get a token for a testuser
35. Commit the latest work done in the local git repository by running the next two highlighted commands.
git add .
git commit -m "DjangoRestFramework(DRF)-simplejwt Implemented(JWT)"
Part7 Adding dj-rest-auth to the API
In this part we will add dj-rest-auth to the mix, it helps us with authentication capabilities to our api by providing login, logout, password/reset, and password/reset/confirm urls.
36. Install the dj-rest-auth by running the next highlighted command from the project’s root path
pipenv install dj-rest-auth |
37. Open the libraray_api/settings.py file by running the next highlighted command from the project’s root pathcode library_api/settings.py and edit it by firstly, adding 'dj_rest_auth', to the INSTALLED_APPS Array and secondly, adding 'rest_frameworkk.authtoken' to the INSTALLED_APPS Array
38. Open library_api/urls.py file by running the next highlighted command from the project’s root path code library_api/urls.py then edit it by adding the next highlighted path item in the urlpatterns array path('api/v1/dj-rest-auth/', include('dj_rest_auth.urls')),
39. Perform the migration by running the next highlighted command from the project’s root path
python manage.py migrate |
40. Spin up the django development server by running the next highlighted command from the project’s root path python manage.py runserver then using your favorite browser visit **127.0.0.1:8000/api/v1/dj-rest-auth/**login and related urls as shown in the next few images.
Logout
Password reset
Password Reset Confirm
Interlude
Run the following git commands to update the repository status and commit the changes.
git add .
git commit -m "Dj-Rest-Auth Implemented"
Part8 Including registration with social accounts
The main theme in this part is the installation basic configuration of the django-allauth package, which enables us to extend the API implementation by adding the registration, and login capability of the API from within itself, and furthermore by utilizing third-parties oauth service providing applications like facebook, google, instagram, linkedin, and so forth. After that introduction let’s proceed as follows.
41. Install the django-allauth package by running the next highlighted command from the project’s root path
pipenv install django-allauth |
42. Open the library_api/settings.py file by running the next highlighted command from the project’s root path code library_api/settings.py then edit it by adding all the items with #new comments besides as shown in the next image
43. Open the library_api/urls.py file by running the next highlighted command from the project’s root path code library_api/urls.py and edit it by adding the following highlighted path item path('api/v1/dj-rest-auth/registration/',includes('dj-rest-auth.registration.urls')), in the urlpatterns array.
44. Perform migrations by running the next highlighted command from the project’s root path
python manage.py migrate |
45. Spin up the django development server by running the next highlighted command from the project’s root path python manage.py runserver then using your favorite browser visit 127.0.0.1:8000/api/v1/dj-rest-auth/registration Registration
Register auth form
For the sake of brevity, extra implementation of signing up and signing in with social networking sites like gmail, linkedin, and twitter and the like has been omitted from this tutorial.
Interlude
Run the following git commands to update the repo status and commit changes made.
git add .
git commit -m "django-allauth setup ready"
Part 9 Before we go:
Before we call it a day it is better to make some little adjustments to our development project resources so as to make it easy for transition or otherwise simplify integration with the other/collaborating front end side team. The adjustments will involve 1.pagination feature, 2. Django-cors installation and configuration, 3. Disabling browsable api to get ready for production and 4. Performing another git commit for our MVP API product and pushing the changes made to our remote git repo.
- Introducing pagination to our views: As you have already seen we just had a little sample data to visualize how our api will work. It is however inevitable that the amount of data held in our production version of the system is going to be large and continuously tend to be larger with time. For that reason it is common wisdom to have a pagination feature implemented along all the Listing pathways of our api. In our particular case those listing pathways are /categories, /ebooks, /reviews, and /users with GET as the request method. Now we implement the pagination feature in order to reduce the dataset returned by queries from the potential several hundredths or thousandths to just few paged dataset results in order of ten or twenty(more or less) whichever is suitable for a given scenario. This helps to boost performance and user experience as a whole.
To add pagination please open the library_api/settings.py file and edit it by adding the DEFAULT_PAGINATION_CLASS array with values set as shown next within the REST_FRAMEWORK object
2. Adding django-cors: For the cross-origin requests handling we need to install and configure the django-cors package within our django project. While the project is still under development phase there might not be strict ruling as to which origins(which imply the combinations of protocols, domains and ports) are allowed to access the api. But once the project reaches the production environment special attention is given to such stuff as the bears contentious security repercussions if not attended well.
To install django core run the following highlighted command from within the project’s root folder pipenv install django-cors-headers
After installing django-cors-headers we need to add some configuration changes by opening the library_api/settings.py file and edit it as explained next. Add ‘corsheaders’ to the INSTALLED_APPS array and perform the followings two changes; first insert corsheaders.middleware.CorsMiddleware to the middleware to the middleware array as shown in the next image
(Please note that the order should be as shown above and not otherwise),secondly add the next bolded text CORS_ALLOWED_ORIGIN=env.list(
‘CORS_ALLOWED_ORIGINS’)
somewhere within the settings.py file as shown in the image below
and also remember to add the specific cors_allowed_origins relevant to your environment/s and project in the .env, and the respective .envExample files. If not ready just add an empty array for the cors_allowed_origins in the .env and .envExample as shown next in bolded text CORS_ALLOWED_ORIGINS=[]
3. Turn off browsable api feature: The browsable api feature is very good while the project is still in development stages as it simplifies the api visualization to the development team. In the production environment such a feature is not encouraged as it exposes a lot of information which is not of necessity to the third parties. To turn off the browsable api by opening the library_api/settings.py file and edit it by adding the JSONRenders as default Renderer to the Rest framework object as shown in the image below.
For documenting the api to both internal and external parties there exists other popular solutions in the market such as the Swagger API also known as OpenAPI.
4. Perform another git commit and push the changes to the remote git repository as explained next.
git commit -m "cors, default render json, and pagination implemented"
In order to save the source code to the remote git registry(the likes of Github, Gitlab, and Bitbucket) you need to have an account with the respective git registry. I will use bitbucket.org in this particular case and the respective account and repository which in my case is https://bitbucket.org/barakaben/library_api.git (a public git repository).
After you have signed up for bitbucket.org you may create your own git repository for this project in your respective account(while signed in) at the create new repository link which once clicked opens up a form, just provide the data required for repository name(library_api) and any name for workspace, and be careful enough to exclude gitignore, and README.md files before hitting the submit button by unchecking the respective checkboxes on the form. You may also set the repository as public or private depending on your choice. For pushing the changes in our local repository to the remote git we use git remote add origin and git push commands as shown below. A word of caution, before issuing the git push command you need to make sure that you have set up an ssh authentication and authorization for your machine with the respective git repository. Be sure to replace the username appearing between https://bitbucket.org and the repository name which is barakaben in my particular case to whatever unique username that you have set up for your respective bitbucket account for the below commands to run effectively.
git remote add origin https://bitbucket.org/barakaben/library_api.git |
You may run the git remote -verbose command to confirm the addition of git remote repository as shown below.
Finally push the changes to the remote repository by running the following command
git push |
To learn about bitbucket ssh authentication procedures on linux machine, you may visit https://support.atlassian.com/bitbucket-cloud/docs/set-up-personal-ssh-keys-on-linux/ and to learn about bitbucket repository authorization with app passwords visit https://support.atlassian.com/bitbucket-cloud/docs/using-app-passwords/.
Conclusion
That is it. We now have the source code in both our local and remote repositories. This paves the way for ease implementation and integration with other frontend apps for the library api in other environments such as testing, staging, and production.