This article is an article about creating a RESTful API using a lightweight Python framework called Flask.
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.
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.
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.
.
├── 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
setUp.sh
docker-compose build
docker-compose up -d
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
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)
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
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()
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)
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
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'})
flask official reference flask-sqlalchemy official reference Flask – SQLAlchemy yoshiya0503 / Hermetica 04 View and RESTful API Easy to use Flask
Recommended Posts