Фреймворк flask.

Встановимо flask.

 pip install flask

Створимо мінімальний додаток run.py.

from flask import Flask
app = Flask(__name__)

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

Для того, щоб запускати програму, необхідно мати змінну FLASK_APP в оточенні командного інтерпретатора bash.

Її можна додати до адресного рядка.

export FLASK_APP=start.py

Або додати цей рядок в .bashrc файл для того, щоб він був присутній при будь-якому запуску терміналу.

Але ми створимо файл .env c змінними, які мають входити до оточення.

FLASK_APP=run.py

Тепер нам потрібна бібліотека, яка здатна його прочитати та додати ці змінні в оточення (конфігурацію програми) на етапі виконання програми.

Одна з таких бібліотек називається dotenv.

pip install python-dotenv

Тепер створимо функцію створення програми із заданою конфігурацією.

from flask import Flask
from dotenv import load_dotenv, dotenv_values

def create_app():
    flask_app = Flask(__name__)
    load_dotenv()
    flask_app.config.update(dotenv_values())
    return flask_app

app = create_app()

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

Додамо ще пару змінних у в .env.

FLASK_APP=run.py
DEBUG = True
FLASK_ENV=development

DEBUG - режим налагодження

FLASK_ENV -режим, коли програма буде перевантажуватися при змінах скриптів.

Наприклад так:

 * Detected change in '/home/zdimon/Desktop/flask-api/run.py', reloading
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 319-920-800

Альтернативним способом можна налаштувати оточення не через .env файл, а через класи у файлі, наприклад, у configmodule.py:

class Config(object):
    DEBUG = False
    TESTING = False
    DATABASE_URI = 'sqlite:///:memory:'

class ProductionConfig(Config):
    DATABASE_URI = 'mysql://user@localhost/foo'

class DevelopmentConfig(Config):
    DEBUG = True

class TestingConfig(Config):
    TESTING = True

І потім “вштовхнути” в додаток так:

 app.config.from_object('configmodule.ProductionConfig')

Перенесення роутів в окремий файл.

Ми можемо перенести роути в окремі файли і не зберігати все в run.py

Облеггим до краю run.py

from app import app
import apps

if __name__ == '__main__':
    app.run(host='0.0.0.0')

Винесемо налаштування програми в окремий модуль app.py

from flask import Flask
from dotenv import load_dotenv, dotenv_values

def create_app():
    flask_app = Flask(__name__)
    load_dotenv()
    flask_app.config.update(dotenv_values())
    return flask_app

app = create_app()

У новій папці apps/route створимо модуль index.py

from app import app

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

І для того, щоб спрацював імпорт import apps в run.py додамо наступне в apps/init.py

 від .route.index import index

Тут ми імпортуватимемо кожен новий модуль роутів.

База даних

Встановимо бібліотеки

 pip install Flask-SQLAlchemy psycopg2-binary

Створимо об’єкт бази даних у app.py

...

from flask_sqlalchemy import SQLAlchemy

def create_db(c_app):
    return SQLAlchemy(c_app)


...

app = create_app() 
db = create_db(app)

Для підключення до БД необхідно встановити спеціальні змінні в оточенні.

Посилання на документацію

Задаємо змінну SQLALCHEMY_DATABASE_URI з правами та іншим для коннекту.

 SQLALCHEMY_DATABASE_URI=postgresql://postgres:1q2w3e@localhost:5432/flask-api

Створимо клас моделі даних у новій папці models та у файлі users.py

from app import db

class Users(db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String())
    password = db.Column(db.String())

    def __repr__(self):
        return '<id {}-{}>'.format(self.id, self.username)

Тепер для того, щоб додати цю таблицю, необхідно створити та запустити міграцію.

Для цього встановимо інструмент flask-migrate

pip install flask-migrate

Створимо об’єкт міграцій у app.py

from flask_migrate import Migrate
...
app = create_app() 
db = create_db(app)
migrate = Migrate(app, db)

Створимо базу даних fask-api у будь-якому клієнті postgres наприклад у pgAdmin3

Тепер у нас стала доступною команда

flask db

Наступним кроком буде створення репозиторію (директорії) для міграцій.

 flask db init

І далі створення першої міграції.

flask db migrate

При цьому отримуємо

 No changes in schema detected.

Імпортуємо моделі після створення об’єкта міграцій у app.py

...
migrate = Migrate(app, db)
from apps.models.users import Users

Тепер можна послідовно запускати команди

 flask db migrate

Яка створить міграцію.

І другою командою її запустити.

flask db upgrade

Установка swagger

Ця бібліотека створить зручний інтерфейс для тестування.

 pip install flasgger

Створюємо об’єкт Swagger із програми.

from flasgger import Swagger
swagger = Swagger(app)

Додаємо опис у функцію роутингу.

from app import app

@app.route('/')
def index():
    """Example endpoint returning a list of colors by palette
    This is using docstrings for specifications.
    ---
    parameters:
      - name: palette
        in: path
        type: string
        enum: ['all', 'rgb', 'cmyk']
        required: true
        default: all
    definitions:
      Palette:
        type: object
        properties:
          palette_name:
            type: array
            items:
              $ref: '#/definitions/Color'
      Color:
        type: string
    responses:
      200:
        description: A list of colors (may be filtered by palette)
        schema:
          $ref: '#/definitions/Palette'
        examples:
          rgb: ['red', 'green', 'blue']
    """
    return 'Hello, World!'

ИВикористання схем Marshmallow.

Ці схеми дозволяють перетворювати python об’єкти схем моделі на json.

Встановлюємо бібліотеку.

 pip install marshmallow apispec

Створимо новий модуль schemas/user.py

from flasgger import Schema, fields

class User(Schema):
    name = fields.Str()
    username = fields.Str()
    password = fields.Str()

Створимо контролер (подання) у новому модулі routes/users.py

from flasgger import Swagger, SwaggerView
from ..shemas.user import User
from app import app

class UsersView(SwaggerView):
    parameters = [
        {
            "name": "name",
            "type": "string",
            "required": True,
        },
        {
            "name": "username",
            "type": "string",
            "required": True,
        },
        {
            "name": "password",
            "type": "string",
            "required": True,
        }
    ]
    responses = {
        200: {
            "description": "Create user",
            "schema": User
        }
    }

    def post(self):
        """

        Creating a new user.

        """

        return jsonify({'message': 'Ok'})

app.add_url_rule(
    '/user/create',
    view_func=UsersView.as_view('create user'),
    methods=['POST']
)

Підключимо цей роут до apps/init.py

 from .routes.users import UsersView

Додамо файл до параметрів.

class UsersView(SwaggerView):
    parameters = [
        ...
        {
            "name": "file",
            "type": "file",
            "required": False,
        }
     ....