Tuesday, January 16, 2018

Django REST API using code first approach

In the previous post we have set up the application with JWT authentication.

In this post we will learn about how to use a code first approach to create api through which you can add, edit, delete and read the data in the table.
Given below are the steps -
1) Create a model with name and desc as text fields.


class mytable(models.Model):
    name=models.CharField(max_length=200)
    desc=models.TextField()


2) Migrate the changes to the database by
    a) Cerate the list of changes to be migrated to the database using the command - python manage.py makemigrations
    b) Add the changes to the table - python manage.py migrate
   
3) Create a file called serializers.py inside the app and add the code below -

   
class mytables(serializers.ModelSerializer):
        class Meta:
            model=mytable
            fields=('name','desc')
    


4) Next we need to add views to define the web api in views.py:
    a) Add the below imports into the code -
        from django.shortcuts import render
        from azure.servicebus._http import HTTPResponse
        from .models import *
        from .serializers import *
        from rest_framework.views import APIView
       
    b) Add the below code for reading the data in the table -

   
        class my_list(APIView):
            def get(self,request,format=None):
            dat=mytable.objects.all() #to get all the data from the table
            serialized=mytables(dat,many=True) #to serialize the data
            return Response(serialized.data) #to return the serialized data

   
    c) To insert data into the table -
        @api_view(('POST','PUT'))
        def test_insertmod(request):
            try:
                indata=request.POST.get('name')
                indesc=request.POST.get('desc')
                inkey=request.POST.get('key')
                testinstance=mytable.objects.create(id=inkey,name=indata, desc=indesc)
                return Response('Successfully inserted')
            except Exception as e:
                print(e)
                return(e)

   
    d) To update the data in the table
   
   
        @api_view(('POST','PUT'))
        def test_insertmod(request):
            try:
                indata=request.POST.get('name')
                indesc=request.POST.get('desc')
                inkey=request.POST.get('key')
                testinstance=mytable.objects.create(id=inkey,name=indata, desc=indesc)
                return Response('Successfully inserted')
            except Exception as e:
                print(e)
                return(e)

   
    e) To delete the data in the table -
   

@api_view(('POST','PUT'))
def test_deletemod(request):
    try:
        indata=request.POST.get('name')
        testinstance=mytable.objects.get(name=indata)
        testinstance.delete()
        return Response('Successfully deleted')
    except Exception as e:
        print(e)
        return(e)



5) Now that we have the views in place, we need to make the urls so that the views can be accessible -
    url(r'^mylist/', views.my_list.as_view()),
    url(r'^modinsert/',views.test_insertmod),
    url(r'^modupdate/',views.test_updatemod),
    url(r'^moddelete/',views.test_deletemod),


Now that we are done, start the django project and use the postman in chrome to test it -

Please ensure that you have the url authorized using the link http://127.0.0.1:8000/webs/auth-jwt/ and authenticating the api using the userid and password.

1) To insert data into the table - http://127.0.0.1:8000/webs/modinsert/

   

   

2) To read the data in the table use the url - http://127.0.0.1:8000/webs/mylist/


3) To update the data in the table use the url - http://127.0.0.1:8000/webs/modupdate/





4) To delete a key in the table use the link - http://127.0.0.1:8000/webs/moddelete/



   

Monday, January 15, 2018

Setting up Django Rest API with JWT authentication - Part 1

In this post, I will cover how to setup project and application for REST API and secure it using JWT.

Software used -
1) OS - Windows 10
2) Python - 3.6 (command: Python --version)
3) Django - 1.11.2 (Command: python -c "import django; print(django.get_version())")
4) Django Rest Framework - 3.6.3
5) Django Rest Framework JWT - 1.11.0 dist
6) Eclipse IDE

Setting up of Project and folder structures

Step 1 - Create a django project by clicking on File > New > Other and then selecting PyDev Django Project

Step 2 - Open command prompt and go to the location where the project is present and type the below command -
    django-admin.py startproject djangowebs
   
    Then in order to create an app inside the project you need to use
    python manage.py webs
    You can have any name of your choice in place of webs.

Configuration of the database and authentication    

Step 3 - Open the settings.py in your project and add the below one in place of the existing DATABASES (This will be pointing to sqllite3 by default). I have used postgres in this case.


    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': '<Name of the database>',
            'USER': '<Name of the user having access to db>',
            'PASSWORD': '<PASSWORD>',
            'HOST': '<Server name or ipaddress>',
            'PORT': '<Port number, if it is default it can be left blank>',
        }
    }

   
Step 4 - Now, lets move the authentication tables into the database. This is done in 3 steps:
    a) To allow django to make scripts for migration using the command -
        python manage.py makemigrations
    b) To make the changes into the database based on the configurations made in Step 3 -
        python manage.py migrate
    Once this is done, login into the database and ensure that the new tables and functions (in case of postgres) appear in the database.
    c) To create a superuser who has complete access to the entire db and application.
        python manage.py createsuperuser
        This will prompt you for userid and password along with confirmation of password.
       
    Once you add this, start the app: this usually will be http://127.0.0.1:8000/admin
    login using the superuser created above and it should allow you to login.



Django App Settings:

Step 5 - Add the below to your INSTALLED_APPS

    'webs',  -> This will be the app you just created in step 2
    'rest_framework.authtoken', -> This is used for authentication
    'rest_framework_jwt',  -> This is used for authentication via JSON Web Tokens (JWT)

Your INSTALLED_APPS should look like the below:


        INSTALLED_APPS = [
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'rest_framework',
            'webs',
            'rest_framework.authtoken',
            'rest_framework_jwt',
        ]


Step 6 - In order to use JWT based authentication you need to add REST_FRAMEWORK. Please ensure the order is maintained as shown in the snippet below:
        REST_FRAMEWORK = {
            'DEFAULT_AUTHENTICATION_CLASSES': (
                'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
                'rest_framework.authentication.TokenAuthentication',
                'rest_framework.authentication.BasicAuthentication',
                'rest_framework.authentication.SessionAuthentication',
            ),
            'DEFAULT_PERMISSION_CLASSES': (
                'rest_framework.permissions.IsAuthenticated',
                #'rest_framework.permissions.AllowAny', (To be used instead of IsAuthenticated if you do not want any authentication for the web API)
            )
        }


Step 7 - Add the below for JWT settings:

       
JWT_AUTH = {
            'JWT_ENCODE_HANDLER':'rest_framework_jwt.utils.jwt_encode_handler',
            'JWT_DECODE_HANDLER':'rest_framework_jwt.utils.jwt_decode_handler',
            'JWT_PAYLOAD_HANDLER':'rest_framework_jwt.utils.jwt_payload_handler',
            'JWT_PAYLOAD_GET_USER_ID_HANDLER':'rest_framework_jwt.utils.jwt_get_user_id_from_payload_handler',
            'JWT_RESPONSE_PAYLOAD_HANDLER':'rest_framework_jwt.utils.jwt_response_payload_handler',
            'JWT_SECRET_KEY': SECRET_KEY,
            'JWT_GET_USER_SECRET_KEY': None,
            'JWT_PUBLIC_KEY': None,
            'JWT_PRIVATE_KEY': None,
            'JWT_ALGORITHM': 'HS256',
            'JWT_VERIFY': True,
            'JWT_VERIFY_EXPIRATION': True,
            'JWT_LEEWAY': 0,
            'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300),
            'JWT_AUDIENCE': None,
            'JWT_ISSUER': None,
            'JWT_ALLOW_REFRESH': True,
            'JWT_REFRESH_EXPIRATION_DELTA': datetime.timedelta(days=7),
            'JWT_AUTH_HEADER_PREFIX': ('JWT','Bearer'),
            'JWT_AUTH_COOKIE': None,
        }

       
Step 8 - Setting up urls in the project to make it understand the app which you have installed.

        url(r'^webs/',include('webs.urls')),
       
        Your urls.py in the main project file should look like:

       
        from django.conf.urls import url, include
        from django.contrib import admin

        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^webs/',include('webs.urls')),
        ]

       

Step 9 - Setting up the app urls for authentication related tasks
       
        imports which need to be added:

       
        from rest_framework_jwt.views import obtain_jwt_token
        from rest_framework_jwt.views import refresh_jwt_token
        from rest_framework_jwt.views import verify_jwt_token

       
        urls which need to be added within urlpatterns -
       
        url(r'^auth-jwt/', obtain_jwt_token),
        url(r'^auth-jwt-refresh/', refresh_jwt_token),
        url(r'^auth-jwt-verify/', verify_jwt_token),

       
To test the above application -

1) use http://127.0.0.1:8000/admin and provide userid and password used for superadmin, it should allow you to login.
2) To test the JWT part, install postman plugin in chrome, then provide the url along with User ID and password used for super admin in header and you can see the token as shown in the image below. 




In the up coming posts, I shall cover
1) Creating CRUD rest api using code first approach.
2) Creating CRUD rest api using database first approach using sqlalchemy
3) Creating CRUD rest api using stored procedure / functions in database and not using any ORM.