[DOCKER] Try to make RESTful API with MVC using Flask 1.0.2

This article is an article about creating a RESTful API using a lightweight Python framework called Flask.

Introduction

Many articles have already been written about RESTful APIs using Flask, but Flask has also evolved considerably recently so that it can describe modern times that are a little different from the literature two or three years ago. It has become.

The number of cases where Python is adopted as the designated language is increasing even in the technical test of the internship, and I did not have enough coding skills to apply Python, so I studied using Flask, which I had been interested in for a long time. I decided to see it.

It turns out that the recent fashion of Flask seems to be a combination of a library called Flask-SQLAlchemy, which was created by wrapping a Python ORM called SQLAlchemy, and model description with Active Record. I will create it.

Why Flask?

Before getting into the main subject, I will also explain why I chose the framework called Flask.

I believe that the biggest barrier to learning a framework is the cost of learning. In particular, Web API has many functions that are not used among the functions required for Web applications such as session management and View generation.

Therefore, it is very effective not to spend unnecessary learning cost, and I personally use PHP Slim as a thin framework. In Python, the Flask framework is famous for its thin framework, so I chose Flask this time.

Environment

Docker is used every time to build the environment.

There are two containers used this time, a Python execution container and a MySQL container. As for MySQL, there is no special package required, so use the MySQL container as it is. For the Python execution container, Flask, SQLAlchemy, and mysqlclient need to be installed with pip.

Please refer to Completed repository because only the important part is described.

Execution environment

Final directory structure

.
├── Build
│   └── app
│       ├── Dockerfile
│       └── requirements.txt
├── DB
├── LICENSE
├── README.md
├── docker-compose.sample
├── docker-compose.yml
└── share
    ├── app.py
    ├── controllers
    │   ├── __init__.py
    │   ├── top_controller.py
    │   └── user_controller.py
    ├── db.py
    └── models
        ├── __init__.py
        └── user.py

Dockerfile Dockerfile is described as follows The path is Build / app / Dockerfile Move this Dockerfile to the / web directory, copy requirements.txt into the container, and pip install it.

#Specifying the base image
FROM python:3.6.5

#Store the directory where the source is placed as a variable
ARG project_dir=/web/

#Copy required files from local to container
ADD requirements.txt $project_dir

# requirements.Install the package listed in txt
WORKDIR $project_dir
RUN pip install -r requirements.txt

Start Docker container

setUp.sh


docker-compose build
docker-compose up -d

Implementation

After completing the environment construction, actually implement it. Implementation proceeds according to the following procedure.

--Start Flask's built-in server and set db. --Create a model --Create a controller

About the basic specifications of Flask

About the built-in server

To develop an application in Flask, execute the run method of the app object and start the built-in server. You can start Flask at least by writing the following 7 lines.

app.py


from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=80, debug=True)

About config

You can describe your application's settings by adding values to the array in app.config. This time, set the database and character code. The database settings are in the order of user name, password, host name, and database name.

app.py


app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@%s/%s?charset=utf8' % (
    "root",
    "BzHSGDBv2fya",
    "db",
    "database",
)
app.config['JSON_AS_ASCII'] = False

About database settings

Since Flask-SQLAlchemy is used, create an instance with db.py. Create a db instance by writing the following two lines. After that, register the app instance in db like db.init_app (app) in app.py.

db.py


from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()

About routing

Flask's default routing is implemented using a decorator called @ app.route ('/'), but this routing limits the functions that can be called after the decorator to global functions. So, use app.add_url_rule. The following two programs operate in the same way

app.py


@app.route('/')
def get():
    return 'Hello, World!'

app.py


class TopController(MethodView):
    def get(self):
        return 'Hello, World!'

app.add_url_rule('/',view_func=TopController.as_view('top_controller'))

The final app.py looks like this:

app.py


from flask import Flask
from db import db
from controllers.top_controller import TopController
from controllers.user_controller import UserController

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://%s:%s@%s/%s?charset=utf8' % (
    "root",
    "BzHSGDBv2fya",
    "db",
    "database",
)
app.config['JSON_AS_ASCII'] = False
app.secret_key = 'secret'

app.add_url_rule('/', view_func=TopController.as_view('top_controller'))
app.add_url_rule('/<int:id>', view_func=UserController.as_view('user_controller'))


if __name__ == '__main__':
    db.init_app(app)
    app.run(host="0.0.0.0", port=80, debug=True)

Creating a model

Since the model also uses Flask-SQLAlchemy, create it using the db instance. The difference from SQLAlchemy is that you need to prefix it with db, such as db.Column or db.Model. Also, create a very important method, to_dict (). to_dict () is a method to change to dictionary type because model object cannot be handled when creating json as API response after getting model.

Show the created user model,

user.py


from db import db
from datetime import datetime


class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    created_at = db.Column(db.DateTime, nullable=False, default=datetime.now)
    updated_at = db.Column(db.DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)

    def to_dict(self):
        return {
            'id': self.id,
            'username': self.username,
            'email': self.email,
            'created_at': self.created_at.strftime('%Y-%m-%d %H:%M'),
            'updated_at': self.updated_at.strftime('%Y-%m-%d %H:%M'),
        }

    def __repr__(self):
        return '<User %r>' % self.username

[WIP] Creating a controller

Finally, create a controller. I thought about creating a controller the most, but I couldn't find a good method, so for the time being, it became the current form. I think there is a better design method, so I would like to consider it in the future.

TopController is as follows. The point is that it describes the request processing for the base URL. Since userId is not specified, get returns all the data as it is. In post, create a new user. Use jsonify to change the dictionary type to json. Also, whenever you access for the first time, execute db.drop_all () and db.create_all () to create the table.

top_controller.py


from flask import request
from models.user import User
from flask.json import jsonify
from flask.views import MethodView
from db import db


class TopController(MethodView):
    def get(self):
        """
Get all table data
        :return: json
        """
        # db.drop_all()
        # db.create_all()
        return jsonify({"data": [User.to_dict(user) for user in User.query.all()]})

    def post(self):
        """
Create a new user
        :return: json
        """
        username = request.form['username']
        email = request.form['email']
        user = User(username=username, email=email)
        db.session.add(user)
        db.session.commit()
        return jsonify({'response': 'ok'})

reference

flask official reference flask-sqlalchemy official reference Flask – SQLAlchemy yoshiya0503 / Hermetica 04 View and RESTful API Easy to use Flask

Recommended Posts

Try to make RESTful API with MVC using Flask 1.0.2
Try using Dropbox API v2 with Go
How to make an artificial intelligence LINE bot with Flask + LINE Messaging API
Try to make your own AWS-SDK with bash
Flask can't be RESTful with azure API Apps
Try to separate Controllers using Blueprint in Flask
Try to make a "cryptanalysis" cipher with Python
Try slack OAuth authentication with flask (Slack API V2)
Try to make a dihedral group with Python
Try to make client FTP fastest with Pythonista
[First API] Try to get Qiita articles with Python
Try to delete tweets in bulk using Twitter API
How to analyze with Google Colaboratory using Kaggle API
Try to factorial with recursion
Try using PythonTex with Texpad.
Try using matplotlib with PyCharm
Try using the Twitter API
Easy to make with syntax
Try using the Twitter API
Try using the PeeringDB 2.0 API
Try using folium with anaconda
How to make a Cisco Webex Teams BOT with Flask
Try to make it using GUI and PyQt in Python
Try to make PC setting change software using TKinter (beginner)
The first API to make with python Djnago REST framework
Try to determine food photos using Google Cloud Vision API
Image analysis with Object Detection API to try in 1 hour
Try to implement linear regression using Pytorch with Google Colaboratory
Until API made with Flask + MySQL is converted to Docker
Try using Janus gateway's Admin API
Rubyist tried to make a simple API with Python + bottle + MySQL
Try to operate Facebook with Python
Persist Flask API server with forever
Try using Pleasant's API (python / FastAPI)
Try to profile with ONNX Runtime
Try using pynag to configure Nagios
Try to make a web service-like guy with 3D markup language
[Sakura rental server] Try using flask.
Try to get statistics using e-Stat
Try using Python argparse's action API
Try to make capture software with as high accuracy as possible with python (1)
I tried to make a todo application using bottle with python
When you want to send an object with requests using flask
Create API using hug with mod_wsgi
Try to output audio with M5STACK
Try using Python's networkx with AtCoder
Try to create a Qiita article with REST API [Environmental preparation]
Connect to MySQL using Flask SQLAlchemy
The easiest way to make Flask
[TCP / IP] After studying, try to make an HTTP client-like with Python
In Vim: set to output html from markdown using pandoc with make
Fixed to easily realize multifunctional login / logout with Python / Flask using Auth0
Python beginners decided to make a LINE bot with Flask (Flask rough commentary)
Try to make a capture software with as high accuracy as possible with python (2)
Try to make foldl and foldr with Python: lambda. Also time measurement
I tried to make "Sakurai-san" a LINE BOT with API Gateway + Lambda
Try to predict FX with LSTM using Keras + Tensorflow Part 2 (Calculate with GPU)
I tried to make PyTorch model API in Azure environment using TorchServe
I want to make a web application using React and Python flask
Try to poke DB on IBM i with python + JDBC using JayDeBeApi
Try to reproduce color film with Python