[PYTHON] How to create a Rest Api in Django

Introduction

Now that you've learned how to create a REST API in Django, to get a deeper understanding Further flesh out and output. __ I will omit the explanation of environment construction this time. __ __ I am using the environment built in the following article, so please be sure to refer to it. __ Create a virtual environment with Anaconda and link it with PyCharm. Also, please note that all arbitrary names are based on the ones used in the above article.

Advance preparation & environment

・ Chrome Mod Header ・ Postman ・ Anaconda Navigator ・ PyCharm CE ・ MacOS

table of contents

  1. Creating a model
  2. Creating a serializer
  3. Create view
  4. Operation check
  5. Bonus: Set API to be available from front end

1. Creating a model

A model is a Python that allows you to design, create, and operate a database (so-called ORM). The table name is defined using the fields provided by class and column models. You can get each value by specifying auto_now_add = True for the data creation time and auto_now = True for the update time.

models.py


from django.db import models

# Create your models here.
#Database design
class Todo(models.Model):
    title = models.CharField(max_length=50)
    content = models.CharField(max_length=400)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Make migrations and migrate the created model. Of course, I will explain it properly. -Makemigrations: Create migration files for database version control. -Migrate: Change the database configuration or undo the change.

$ python manage.py makemigrations
$ python manage.py migrate

This completes model creation and migrate.

2. Creating a serializer

A serializer is to input / output data to / from the model by changing the data into an appropriate form such as validation and password hashing. It acts as a bridge from the input form to the model that handles the database. Create a new serializers.py directly under the api. Tokens in this chapter are authentication tokens. You can imagine the authentication token as information (character string) for uniquely recognizing the user.

serializers.py


from rest_framework import serializers
from .models import Todo
#Import the User model provided by default in django
from django.contrib.auth.models import User
#Import tokens for users
from rest_framework.authtoken.models import Token

class UserSerializer(serializers.ModelSerializer):
    #Class for basic settings
    class Meta:
        model = User
        fields = ('id', 'username', 'password')
        #password cannot be accessed by GET and must be entered
        extra_kwargs = {'password': {'write_only':True, 'required': True}}

    #Override the create method used to create the user.
    def create(self,validated_data):
        #Hash password
        user = User.objects.create_user(**validated_data)
        #Generate token
        Token.objects.create(user=user)
        return user

class TodoSerializer(serializers.ModelSerializer):

    #Changed django's Datetimefield notation
    created_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M", read_only=True)
    updated_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M", read_only=True)

    class Meta:
        model = Todo
        fields = ['id','title','content','created_at','updated_at']

You have now created a serializer.

3. Create view

Views control data access rights and authentication. It is responsible for allowing CRUD to be handled only by properly authenticated users. Create a permission file before creating views. This is to prevent PUT and DELETE in the User model. Create own permissions directly under api and specify to accept only GET and POST.

ownpermissions


from rest_framework import permissions

class OwnPermission(permissions.BasePermission):

    def has_object_permission(self, request, view, obj):
        #SAFE_GET with METHOD,Only POST allowed
        if request.method in permissions.SAFE_METHODS:
            return True
        return False

Then create the view.

views.py


from django.shortcuts import render

#Library required for token authentication
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated

#Library required to create a view
from rest_framework import generics
from rest_framework import viewsets

#Import the created model and serializer
from django.contrib.auth.models import User
from .models import Todo
from .serializers import UserSerializer,TodoSerializer

#Import the created permission
from .ownpermissions import OwnPermission

class UserViewSet(viewsets.ModelViewSet):

    #Get all user objects
    queryset = User.objects.all()

    #Specify the serializer to use
    serializer_class = UserSerializer

    #Specify so that anyone can see it
    permission_classes = (OwnPermission,)

class ManageUserView(generics.RetrieveUpdateAPIView):
    serializer_class = UserSerializer

    #Specify that only authenticated users can access
    authentication_classes = (TokenAuthentication,)

    #Specify to allow only logged-in users
    permission_classes = (IsAuthenticated,)

    #A function that returns logged-in user information
    def get_object(self):
        return self.request.user

class TodoViewSet(viewsets.ModelViewSet):
    queryset = Todo.objects.all()
    serializer_class = TodoSerializer
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

The view is now complete.

Let's also create urls. urls are responsible for linking views and paths. Make the following edits to both your project and your app. (Create a new app)

drfapi/urls


from django.contrib import admin
from django.urls import path
from django.conf.urls import include
from rest_framework.authtoken.views import obtain_auth_token

urlpatterns = [
    path('admin/', admin.site.urls),
    #Go see the api urls
    path('api/',include('api.urls')),
    #POSTing a username and password returns a token.
    path('auth/',obtain_auth_token ),
]

Models inherited from generics use as_view () to associate the view with the path.

api/urls


from django.urls import path
from django.conf.urls import include
from rest_framework import routers
from api.views import UserViewSet, ManageUserView, TodoViewSet

router = routers.DefaultRouter()
router.register('users',UserViewSet)
router.register('todolist',TodoViewSet)

urlpatterns = [
    path('myself/',ManageUserView.as_view( ), name='myself'),
    #POSTing a username and password returns a token.
    path('',include(router.urls)),
]

6. Operation check

First, check the admin dashboard to see if the model works properly. Write a function that returns the title name to models.py, and code that makes Todo recognized by admin in admin.py.

models.py


def __str__(self):
   return self.title

admin.py


from django.contrib import admin
from .models import Todo
#Register Todo as admin
admin.site.register(Todo)

You need a super user (authorized user) to log in to the admin dashboard. The super user (authorized user) is created from the terminal.

When you enter the following command, a response will be returned, so enter name, email, password. You can leave the email blank. If it is a simple password, you will be warned, but if there is no problem, enter y.

$ python magange.py createsuperuser
Username (leave blank to use host name): admin
Email address: 
Password: 
Password (again): 
The password is too similar to the username.
This password is too short. It must contain at least 8 characters.
This password is too common.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

Now let's use the admin dashboard. Execute manage.py and add "/ api / users" to the URL of the local host to access it. Enter your username and password to log in. スクリーンショット 2020-09-26 23.06.20.png After logging in, enter the title and content from [ADD TO DO] of Todos. スクリーンショット 2020-09-26 23.15.44.png If you can save it as shown in the image below, the model is working properly. スクリーンショット 2020-09-26 23.16.02.png

Next, use Postman to check the operation of CRUD. While running manage.py as before, add "/ api / users" to the URL of the local host and access it. Enter your username and password to POST and GET again. If the value is updated as shown in the image below, USER's GET and POST communication is successful. スクリーンショット 2020-09-26 23.22.40.png

Next, let's access Todolist. Convert the "users" part of the URL to "todolist" and access it. スクリーンショット 2020-09-26 23.28.05.png I've been warned that I don't have CRUD privileges unless I'm an authenticated user. This is because I wrote in views.py that user authentication is required.

Access using the authentication token. The authentication token is obtained from Postman.

Start Postman. When it starts, press the white "+" button. スクリーンショット 2020-09-27 9.20.07.png Enter the URL with "auth" added. Select POST for the Http request. Create a username and password field from Body> form-data and enter the existing VALUE. When you press SEND, the token will be returned and you can copy it. スクリーンショット 2020-09-27 9.32.41.png Launch chrome ModHeader from your browser. Press the "+" button Select Authorization and enter Token "copied token". (Half-width space after Token) スクリーンショット 2020-09-27 9.36.43.png You can now also access the Todolist.

5. Bonus: Set API to be available from front end

Install CORS. CORS is a system that consists of forwarding HTTP headers that determines whether the browser blocks the front-end JavaScript code from accessing the response of a cross-origin request. By the way, the origin is a combination of "scheme (protocol)", "host (domain)" and "port" of the URL of the resource itself.

$ pip install django-cors-headers

Make Django aware of CORS.

setting.py


INSTALLED_APPS = [
   #<Abbreviation> 
   'corsheaders',
]

MIDDLEWARE = [
   #<Abbreviation>
   'corsheaders.middleware.CorsMiddleware',
]

CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000',
]

You can now access it from the front end. In the next article, I'd like to summarize how to access the API from the front side.

References

・ Overview of Django (https://docs.djangoproject.com/ja/3.1/intro/overview/) -Let's create a device management tool with the Django REST API (https://www.udemy.com/course/django-rest-api/) ・ [Learning memo] About Make migrations and Migrate (https://qiita.com/frosty/items/8c715a53d7920c9cd1eb) ・ I summarized what I learned from the Django REST framework (https://qiita.com/breakthrough/items/f845592961d8863a72c5). ・ MDN (https://developer.mozilla.org/ja/docs/Glossary/CORS)

Recommended Posts

How to create a Rest Api in Django
Create a REST API to operate dynamodb with the Django REST Framework
How to create a JSON file in Python
How to reference static files in a Django project
Steps to create a Django project
How to create a Conda package
How to create a virtual bridge
How to reflect CSS in Django
How to create a Dockerfile (basic)
How to create a config file
Create a LINE Bot in Django
How to write custom validations in the Django REST Framework
How to reset password via API using Django rest framework
How to generate a query using the IN operator in Django
I want to create an API that returns a model with a recursive relationship in the Django REST Framework
How to create a git clone folder
How to delete expired sessions in Django
How to create a repository from media
How to do Server-Sent Events in Django
How to convert DateTimeField format in Django
[Python / Django] Create a web API that responds in JSON format
How to create a heatmap with an arbitrary domain in Python
How to create a large amount of test data in MySQL? ??
How to deploy a Django app on heroku in just 5 minutes
Try to create a Qiita article with REST API [Environmental preparation]
How to create a serverless machine learning API with AWS Lambda
Create a Django schedule
How to create a Python virtual environment (venv)
How to clear tuples in a list (Python)
How to implement Rails helper-like functionality in Django
How to embed a variable in a python string
How to create a function object from a string
How to develop a cart app with Django
I want to create a window in Python
How to reflect ImageField in Django + Docker (pillow)
Let's create a REST API using SpringBoot + MongoDB
How to run some script regularly in Django
How to implement a gradient picker in Houdini
How to create data to put in CNN (Chainer)
How to get a namespaced view name from a URL (path_info) in Django
How to notify a Discord channel in Python
Django REST framework A little useful to know.
How to create a shortcut command for LINUX
How to create a Kivy 1-line input box
How to create a multi-platform app with kivy
[Python] How to draw a histogram in Matplotlib
Until you create a new app in Django
How to write a named tuple document in 2020
How to deal with garbled characters in json of Django REST Framework
How to count numbers in a specific range
How to make a request to bitFlyer Lightning's Private API in Go language
How to read a file in a different directory
How to Mock a Public function in Pytest
[Note] How to create a Mac development environment
How to get people to try out django rest framework features in one file
Create a REST API using the model learned in Lobe and TensorFlow Serving.
How to count the number of elements in Django and output to a template
How to automatically generate API document with Django REST framework & POST from document screen
Create a filter to get an Access Token in the Graph API (Flask)
Read the Python-Markdown source: How to create a parser
A memo to create a virtual environment (venv) before Django