Topics -> djangorestframework, python, webdevelopment, API
Source Code Link -> GitHub
What We are going to do?
- Starting the stock_rest_api django Project
- Creating a companies app within the stock_rest_api Project
- Create a Stock in companies/models.py
- Writing serializers for companies model data
- Creating a view for handling the request made from the client
- Adding function handlers to routes
Understanding Some Important Concepts
What is Django Framework?
Django is a Python-based free and open-source web framework that follows the model–template–views architectural pattern.
Top Features of Django Framework
- Excellent Documentation
- SEO Optimized
- High Scalability
- Versatile in Nature
- Offers High Security
- Provides Rapid Development
Django REST framework ?
Django REST framework is a powerful and flexible toolkit for building Web APIs.
Some reasons you might want to use REST framework:
- The Web browsable API is a huge usability win for your developers.
- Authentication policies including packages for OAuth1a and OAuth2.
- Serialization that supports both ORM and non-ORM data sources.
- Customizable all the way down - just use regular function-based views if you don't need the more powerful features.
- Extensive documentation, and great community support.
- Used and trusted by internationally recognised companies including Mozilla, Red Hat, Heroku, and Eventbrite.
Step 1 => Starting the Django Project
Initialize a Django project by following command. Python must be installed on your system.
pip install Django
You can confirm the installation by checking the django version by following command
python -m django --version
Starting the Project
django-admin startproject stock_rest_api
You get the project structure like this
stock_rest_api/ manage.py stock_rest_api/ __init__.py settings.py urls.py asgi.py wsgi.py
Step 2 -> Creating a companies app within the stock_rest_api Project
What is a Django App?
An app is a Web application that does something – e.g., a Weblog system, a database of public records or a small poll app.
A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.
Creating the companies app
python manage.py startapp companies
That’ll create a directory companies, which is laid out like this:
companies/ __init__.py admin.py apps.py migrations/ __init__.py models.py tests.py views.py
Including your app and libraries in project
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # framework for making rest api 'rest_framework', # our main reusable components 'companies.apps.CompaniesConfig', # authentication 'rest_framework.authtoken', ]
Step 3 -> Create a Stock model in companies/models.py
What is a Django Model?
A model is the single, definitive source of truth about your data. It contains the essential fields and behaviors of the data you’re storing. Django follows the DRY Principle.
The goal is to define your data model in one place and automatically derive things from it.
Let's create a Django Model.
A database contains a number of variable which are represented by fields in django model.Each field is represented by an instance of a Field class – e.g., CharField for character fields and DateTimeField for datetimes. This tells Django what type of data each field holds.
from django.db import models class Stock(models.Model): company_name = models.CharField(max_length=10) open_price = models.FloatField() close_price = models.FloatField() transaction = models.IntegerField() def __str__(self): return self.company_name
Adding models to admin panel
Django provides built-in admin panel to manage the data into model
from django.contrib import admin from .models import Stock # Register your models here. admin.site.register(Stock)
Making migrations
Once the model is defined, the django will automatically take schemas and table according to the fields supplied in the django model.
python manage.py makemigrations python manage.py migrate
Step 4 -> Writing serializers for companies model data
What are Serializers?
Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data.
We are using Model Serializer. But Why?
The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields.
The ModelSerializer class is the same as a regular Serializer class, except that:
- It will automatically generate a set of fields for you, based on the model.
- It will automatically generate validators for the serializer, such as unique_together validators.
- It includes simple default implementations of .create() and .update().
from rest_framework import serializers from rest_framework.serializers import Serializer from .models import Stock from rest_framework import exceptions from django.contrib.auth import authenticate from django.contrib.auth.models import User class StockSerializer(serializers.ModelSerializer): class Meta: model = Stock # for some specific fields = ('companies','open_price') fields = '__all__' class LoginSerializer(serializers.Serializer): username = serializers.CharField() password = serializers.CharField() def validate(self, data): username = data.get("username", "") password = data.get("password", "") if username and password: user = authenticate(username=username, password=password) if user: if user.is_active: data["user"] = user else: msg = "user is inactive" raise exceptions.ValidationError(msg) else: msg = "Wrong credentials" raise exceptions.ValidationError(msg) else: msg = "Must provide username and password both" raise exceptions.ValidationError(msg) return data
Here we are using ModelSerializer for Stock model and Default Serializer for user authentication
Default Serializer has a built-in validate function for validating the data entered
Step 5 -> Creating a view for handling the request made from the client.
What is a Django View?
A view function, or view for short, is a Python function that takes a Web request and returns a Web response.
Http Methods
HTTP Verb | CRUD | Entire Collection (e.g. /customers) | Specific Item (e.g. /customers/{id}) |
---|---|---|---|
POST | Create | 201 (Created), 'Location' header with link to /customers/{id} containing new ID. | 404 (Not Found), 409 (Conflict) if resource already exists.. |
GET | Read | 200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists. | 200 (OK), single customer. 404 (Not Found), if ID not found or invalid. |
PUT | Update/Replace | 405 (Method Not Allowed), unless you want to update/replace every resource in the entire collection. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
PATCH | Update/Modify | 405 (Method Not Allowed), unless you want to modify the collection itself. | 200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid. |
DELETE | Delete | 405 (Method Not Allowed), unless you want to delete the whole collection—not often desirable. | 200 (OK). 404 (Not Found), if ID not found or invalid. |
companies/views.py
from django.contrib.auth import login, logout from rest_framework.authentication import SessionAuthentication, BasicAuthentication, TokenAuthentication from rest_framework.authtoken.models import Token from rest_framework.permissions import IsAuthenticated, IsAdminUser from rest_framework.response import Response from rest_framework.views import APIView from .models import Stock from .serializers import StockSerializer, LoginSerializer class StockApiView(APIView): def get(self, request): stocks = Stock.objects.all() serializer = StockSerializer(stocks, many=True) return Response(serializer.data, status=status.HTTP_200_OK) def post(self, request): data = request.data serializer = StockSerializer(data=data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) class StockApiViewDetail(APIView): authentication_classes = [BasicAuthentication, TokenAuthentication] permission_classes = [IsAuthenticated, IsAdminUser] def get_object(self, pk): try: return Stock.objects.get(pk=pk) except Stock.DoesNotExist as e: return Response({e: "given company stock not found."}, status=404) def get(self, request, pk=None): instance = self.get_object(pk) serializer = StockSerializer(instance) return Response(serializer.data, status=status.HTTP_200_OK) def put(self, request, pk=None): instance = self.get_object(pk) data = request.data serializer = StockSerializer(instance, data=data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) def delete(self, request, pk): instance = self.get_object(pk) instance.delete() return HttpResponse(status=status.HTTP_204_NO_CONTENT) class LoginApiView(APIView): def post(self, request): print(request.user) serializer = LoginSerializer(data=request.data) serializer.is_valid(raise_exception=True) user = serializer.validated_data["user"] login(request, user) token, created = Token.objects.get_or_create(user=user) return Response({"token": token.key}, status=200) class LogoutApiView(APIView): authentication_classes = (SessionAuthentication,) def post(self, request): logout(request) return Response(status=204)
We are using Django Response in-built function.
Arguments:
- data: The serialized data for the response.
- status: A status code for the response. Defaults to 200. See also status codes.
- template_name: A template name to use if HTMLRenderer is selected.
- headers: A dictionary of HTTP headers to use in the response.
- content_type: The content type of the response. Typically, this will be set automatically by the renderer as determined by content negotiation, but there may be some cases where you need to specify the content type explicitly.
Step 6 -> Adding function handlers to routes.(companies/urls.py)
Whenever user visit the user, a function is called in view which takes care of response.
stock_rest_api/urls.py
from django.conf.urls import url, include from django.contrib import admin from rest_framework.urlpatterns import format_suffix_patterns from companies import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^companies/', include('companies.urls')), ]
Adding sub path for companies app(companies/urls.py)
It defines the particular path for companies app
from django.urls import path from . import views app_name = 'companies' urlpatterns = [ # IT IS FOR JSON RESPONSE SERIALIZER # path('', views.stock, name='list'), # path('', views.StockApiView.as_view(), name='list'), path('', views.GenericStockView.as_view(), name='list'), path('<int:pk>/', views.StockApiViewDetail.as_view(), name='detail'), # path('<int:pk>/', views.stock_details, name='detail'), path('login/', views.LoginApiView.as_view(), name="login"), path('logout/', views.LogoutApiView.as_view(), name="logout") ]
Add Some styles to make it attractive
Deployment
You can easily deploy on Heroku
You can read more about on Analytics Vidhya Blog
Web Preview / Output
Placeholder text by Praveen Chaudhary · Images by Binary Beast