[PYTHON] Understand the benefits of the Django Rest Framework

Introduction

This article is a continuation of Last time. The previous article described the conceptual part of the API. This time, I would like to actually build an API using Python and Django. The API created this time is as simple as sending data (from the browser) and saving it in the database, and moving it to any endpoint to display the data in the database. It also builds APIs without using ** Django Rest Framework **. The reason is that I thought that I could understand the convenience of Django Rest framework by building with ** Python code ** without using the framework provided by Django.

Target person

Those who know the basic grammar of Python, those who know the basic mechanism of Django. (Django's installation and installation is omitted considerably.)

Initial setting

The first important part in actually creating the API is the ** what kind of data to handle **. Sending data to the API does not mean that it will be stored in the database without permission, but the API will store the data based on the model of the data designed in ** models.py **. So, first, set the ** what kind of data to handle ** part in the model.

models.py


from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    timestamp = models.DateField(auto_now_add=True)

    def __str__(self):
        return self.title

This time, I designed a model that assumes that blog data is handled by API. Data that has a title, the content of the article, and the date and time of posting. If you can write a model, let's go to ** migrate **. Next, register ** Post ** in ** admin.py ** and enter some test data from the admin page. Enter an appropriate value for each item and save it as shown in the figure below. スクリーンショット 2020-02-06 13.08.20.png

Display data on any endpoint

Now let's display the data saved from the admin page on any endpoint. The first thing to remember is that modern APIs return ** JSON data ** when you send a request. So the return value of the posts function in ** views.py ** is ** JsonResponse **. Other than that, the simple code brings ** QuerySet ** closer to JSON data. Turn the QuerySet with a for statement to make it a dictionary type and put it in the list. From here on, Django will do the work for you, and the dictionary-type data in the Python list will be automatically ** serialized ** into JSON data.

views.py


from .models import Post

def posts(request):

    posts = Post.objects.all()
    post_list = []
    for post in posts:
        post_dict = {
            'pk': post.pk,
            'title': post.title,
            'description': post.description,
            'timestamp': post.timestamp,
        }
        post_list.append(post_dict)

    return JsonResponse(post_list, safe=False)

    # non-To convert dict type data to json data"safe=False"To describe.

Create any endpoint.

urls.py


from application_name.views import posts #add to

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/post/', posts), #add to
]

At this point, let's set up a local server once and move to the created endpoint. I didn't need to enter the primal key this time, but it's convenient when checking during testing like this. I was able to confirm the data properly, so it was a success! Next is the POST request. スクリーンショット 2020-02-06 13.49.16.png

Write processing for POST request

The role of the API with Django is to store new data based on models.py in the database when it is sent through a ** POST request **. It is difficult to understand even if I write a little, so to explain briefly, the role of the API side is to ** process ** and ** save ** the sent data in a form that is easy to save. So next, I will write the code to process and save.

views.py


#Add the following code. The following if statement is written above the processing of the GET request.
from django.http import HttpResponse
import json

def posts(request):

    if request.method == 'POST':
        data = json.loads(request.body)
        post = Post(
            title=data['title'],
            description=data['description'],
            )
        post.save()
        return HttpResponse(201)

    posts = Post.objects.all()
    # ~~The following is omitted~~

** Django ** doesn't have a standard feature to automatically ** deserialize ** (return JSON data to a manageable form) for the JSON data sent, so you need to write the code to deserialize it. You need to write it down. This feature is necessary because it cannot be saved in the database unless it is restored to a data format that can be handled by Python. Put JSON data in an appropriate variable and deserialize (process) using this variable. Also, ** Django ** doesn't have the ability to automatically save data from views, so explicitly write ** post.save ** at the end.

Actually send a POST request

This time I would like to use ** axios ** to send a ** POST request ** to the API. If you want to implement ** ajax ** in your own application, it is recommended to use Javascript's ** axios library **. First, create a page in templates to send a POST request. Add axios to that page using ** cdn **.

main.html



    <body>
        <p>Test Page</p>   
    </body>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script> #Add with cdn
</html>

Created with ** function based ** in view. Also do the routing.

views.py


def main_page(request):
    return render(request, 'main.html', context=None)

urls.py


from application_name.views import main_page #add to

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', main_page),    #Add a route
    path('api/post/', posts),
]

Set up a local server and go to the URL where ** main.html ** is displayed. So let's check if the API works properly from the developer tools ** console **. Since the data sent by POST request must be ** JSON data **, make it a dictionary type. Just make it a variable for the sake of clarity as an argument.

console


/* 
Create an async function
Send request and make response
I want to await because it takes time to send a request
The API endpoint can be a relative path as the server is already up and running
*/

async function addPost(title, description) {
    const response = await axios.post('api/post/', {'title': title, 'description': description})
    console.log(response)
}

//Instantiation
addPost('sending from axios', 'some test messages')

However, doing this should return a ** 403 Forbidden ** error statement. When the 403 comes back like this, you can see all the ** requests ** you have sent in your browser's developer tools ** Network **. As you can see in the image below, you can see the part (data) of the payload you were trying to send. スクリーンショット 2020-02-05 17.09.40.png Next, if you look at the ** Response ** part, you will find ** html statements ** that you often see. To see this response in your browser for clarity, copy the ** response html statement ** and rewrite it with ** innerHTML **. It's a little hard to explain in words, so take a look at the code below.

console


document.querySelector('body').innerHTML = `Response html statement`

If you run it now, you'll see that Django is getting the error. I will put the error screen below. If you look at the error statement, you can see that ** CSRF verification ** has failed. If you are using form in Django, it says that you can use ** csrf_token **, but this time I am sending data using ajax, so this method can not solve it. To do ajax in Django, use a method you don't normally use. スクリーンショット 2020-02-05 17.56.22.png To explain the flow of ** CSRF verification ** in the first place, Django shows that the front side is accessing data from the same site instead of accessing it from another location, and Django receives it. Gives data permissions to the front side. If you think about ** 403 Forbidden ** again with this in mind, you can see that it means "you do not have the authority (permission) to handle data". However, as mentioned earlier, form is not used, so ** csrf_token ** cannot be used. So this time, put csrf_token in ** Cookie ** and paste it in javascript file.

sample.js


axios.defaults.xsrfCookieName = 'csrftoken'
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN"

Originally, by pasting the above code at the top of the ** js file ** that sends the ajax request, you can make the request using axios have ** cookie ** with csrf_token by default. I will. This should resolve the previous error. Since we will not have any functions other than ajax communication using Javascript this time, create a js file with an arbitrary name and write only the above code. Load (connect) this file with ** main.html ** as shown below, and make it work on the console of the developer tools.

main.html



    <body>
        <p>Test Page</p>   
    </body>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script type="text/javascript" src="{% static 'sample.js' %}"></script> #add to
</html>

When I put a value in the argument in the console and instantiate it as before, this time the status code 201 is returned without any error. In other words, it's a success! スクリーンショット 2020-02-05 21.49.44.png For the time being, go to the 'api / post /' endpoint and check if the POSTed data is displayed properly. スクリーンショット 2020-02-05 23.22.02.pngプライマリーキーが3のデータが先ほど追加したデータなので、ちゃんとGET, POSTリクエストが動いていることが分かります。

Why use the Django Rest Framework

First of all, I think the main reason is that using ** Django Rest Framework ** (DRF) greatly reduces the code related to data processing and authentication that we are not dealing with this time. However, I think the next reason is that HTTP verbs such as PUT, PATCH, and DELETE will be available. Normally, ** Django ** ignores these, so you can't use them if you want. ** DRF ** handles other requests easily, so you can maximize the functionality of the API. I think there are many other reasons, but for the time being, I think these two are the major reasons.

Finally

How was the content of the article? It also serves as a memorandum of my own, and it has become quite long, so thank you to those who read it to the end. If you have any mistakes or typographical errors, please feel free to point them out. Next time, I would like to create a simple application using an external API.

Recommended Posts

Understand the benefits of the Django Rest Framework
Miscellaneous notes about the Django REST framework
Django REST framework basics
Django Rest Framework Tips
Create a Todo app with the Django REST framework
[Django Rest Framework] Customize the filter function using Django-Filter
Django REST framework stumbling block
Django REST framework with Vue.js
Login with django rest framework
How to write custom validations in the Django REST Framework
Understand the contents of sklearn's pipeline
The meaning of ".object" in Django
[Django] Use MessagePack with Django REST framework
Implementation of JWT authentication functionality in Django REST Framework using djoser
Implementation of CRUD using REST API with Python + Django Rest framework + igGrid
Create a REST API to operate dynamodb with the Django REST Framework
Create RESTful APIs with Django Rest Framework
I tried the asynchronous server of Django 3.0
Logical deletion in Django, DRF (Django REST Framework)
[Python3] Understand the basics of Beautiful Soup
ng-admin + Django REST framework ready-to-create administration tool
How to check the version of Django
CRUD GET with Nuxt & Django REST Framework ②
[Python] Understand the content of error messages
CRUD POST with Nuxt & Django REST Framework
CRUD GET with Nuxt & Django REST Framework ①
Understand the "temporary" part of UNIX / Linux
Django REST Framework + Clean Architecture Design Consideration
Consider the description of docker-compose.yml (Django + MySQL ③)
[Python3] Understand the basics of file operations
Implementation of custom user model authentication in Django REST Framework with djoser
How to deal with garbled characters in json of Django REST Framework
CRUD PUT, DELETE with Nuxt & Django REST Framework
Exclusive release of the django app using ngrok
Solution when Not Found appears when hitting the Django REST Framework API from the outside
I checked the session retention period of django
Django REST framework A little useful to know.
The story of viewing media files in Django
Implement JWT login functionality in Django REST framework
Knowledge notes needed to understand the Python framework
Implementing authentication in Django REST Framework with djoser
The wall of changing the Django service from Python 2.7 to Python 3
Learning notes for the migrations feature in the Django framework (2)
Create a Todo app with Django REST Framework + Angular
[Trainer's Recipe] I touched the flame of the Python framework.
More new user authentication methods with Django REST Framework
Around the installation of the Python project management framework Trac
A memo to visually understand the axis of pandas.Panel
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 1 ~
[Statistics] Understand the mechanism of Q-Q plot by animation.
Create APIs around user authentication with Django REST Framework
When you want to filter with Django REST framework
I want to fully understand the basics of Bokeh
List method for nested resources in Django REST framework
Implement APIs at explosive speed using Django REST Framework
Learning notes for the migrations feature in the Django framework (3)
[Django] Change the Default IP address of the runserver command
[Ev3dev] Let's understand the mechanism of LCD (screen) control
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 2 ~
Learning notes for the migrations feature in the Django framework (1)
14 quizzes to understand the surprisingly confusing scope of Python