Flask-restful is a Flask extension for quickly building REST apis.

The installation

pip install flask
pip install flask-restfulCopy the code

1 Hello World

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class HelloWorldResource(Resource):
    def get(self):
        return {'hello': 'world'}

    def post(self):
        return {'msg': 'post hello world'}

api.add_resource(HelloWorldResource, '/')

Start here is optional for Flask after 1.0
if __name__ == '__main__':
    app.run(debug=True)Copy the code

Added: If it is after 1.0, it can be run through the Flask application terminal:

$ export FLASK_APP=helloworld  # specifies the name of the program to run$flask run * Running on http://127.0.0.1:5000/Copy the code

It can also be run by changing the parameters of the PyCharm configuration runtime.



The effect of a GET request is as follows:

The effect of a POST request is as follows:


2 the view

2.1 the routing

Name the route using the endpoint parameter

api.add_resource(HelloWorldResource, '/', endpoint='HelloWorld')Copy the code

2.2 the blueprint

from flask import Flask, Blueprint
from flask_restful import Api, Resource

app = Flask(__name__)

user_bp = Blueprint('user', __name__)

user_api = Api(user_bp)

class UserProfileResource(Resource):
    def get(self):
        return {'msg': 'get user profile'}

user_api.add_resource(UserProfileResource, '/users/profile')

app.register_blueprint(user_bp)Copy the code

2.3 a decorator

Add the decorator using method_decorators

  • All methods in the class view add decorators

   def decorator1(func):
      def wrapper(*args, **kwargs):
          print('decorator1')
          return func(*args, **kwargs)
      return wrapper


  def decorator2(func):
      def wrapper(*args, **kwargs):
          print('decorator2')
          return func(*args, **kwargs)
      return wrapper


  class DemoResource(Resource):
      method_decorators = [decorator1, decorator2]

      def get(self):
          return {'msg': 'get view'}

      def post(self):
          return {'msg': 'post view'}Copy the code
  • Different methods in the class view add different decorators

 class DemoResource(Resource):
      method_decorators = {
          'get': [decorator1, decorator2],
          'post': [decorator1]
      }

      Use decorator1 decorator2
      def get(self):
          return {'msg': 'get view'}

      Use the decorator1 decorator
      def post(self):
          return {'msg': 'post view'}

      No decorators used
      def put(self):
          return {'msg': 'put view'}Copy the code

3 the request

Flask-restful provides the RequestParser class to help us validate and transform the request data.

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate cannot be converted', location='args')
parser.add_argument('name')
args = parser.parse_args()Copy the code

3.1 Procedure:

  1. Create a RequestParser object

  2. Add parameter declarations to the RequestParser object that need to be validated or converted

  3. Start the validation processing with the parse_args() method

  4. You can operate according to dictionary operations or object properties when obtaining parameters from the validation results after validation

    The args. Rate or the args ['rate']Copy the code

3.2 Parameter Description

required

Specifies whether the request must carry parameters. The default value is False

  • True Indicates that the carrier is mandatory

    If not, the verification fails and an error message with status code 400 is returned to the client

  • False Not mandatory

    If this parameter is not carried forcibly, the value is None if no parameter is carried in the client request

class DemoResource(Resource):
    def get(self):
        rp = RequestParser()
        rp.add_argument('age', required=False)
        args = rp.parse_args()
        return {'msg': 'data={}'.format(args.age)}Copy the code
help

Error description returned when parameter validation failed

rp.add_argument('a', required=True, help='missing a param')Copy the code
action

Describes what to do when multiple parameters with the same name appear in a request parameter

  • Action =’store’ keeps the first occurrence, default

  • Action =’append’ saves the values of all parameters with the same name in list append

rp.add_argument('age', required=True, help='missing age param', action='append')Copy the code
type

You can use python’s standard data types string and int, or flask-restful, or you can define your own

  • The standard type

    rp.add_argument('age', type=int, required=True, help='missing age param', action='append')Copy the code
  • Flask – RESTful

    Check type methods in the flask_rest. inputs module

    • url

    • Regex (specifies a regular expression)

      from flask_restful import inputs
      rp.add_argument('age', type=inputs.regex(r'^\d{2}&'))Copy the code
    • 0, 1, 2, 3…

    • Positive integer 1, 2, 3…

    • Int_range (low,high) Integer range

      rp.add_argument('age', type=inputs.int_range(1.100))Copy the code
    • boolean

  • The custom

    def mobile(mobile_str):
        "" check mobile phone number format :param mobile_str: STR Checked string :return: mobile_str """
        if re.match(r'^1[3-9]\d{9}$', mobile_str):
            return mobile_str
        else:
            raise ValueError('{} is not a valid mobile'.format(mobile_str))
    
    rp.add_argument('mobile', type=mobile)Copy the code
location

Describes where the parameters should appear in the request data

# Look only in the POST body
parser.add_argument('name', type=int, location='form')

# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')

# From the request headers
parser.add_argument('User-Agent', location='headers')

# From http cookies
parser.add_argument('session_id', location='cookies')

# From json
parser.add_argument('user_id', location='json')

# From file uploads
parser.add_argument('picture', location='files')Copy the code

Multiple locations can also be specified

parser.add_argument('text', location=['headers'.'json'])Copy the code

4 the response

4.1 Serializing Data

Flask-restful provides the Marshal tool, which helps us serialize data into dictionary data in a specific format for use as the return value of the view.

from flask_restful import Resource, fields, marshal_with

resource_fields = {
    'name': fields.String,
    'address': fields.String,
    'user_id': fields.Integer
}

class Todo(Resource):
    @marshal_with(resource_fields, envelope='resource')
    def get(self, **kwargs):
        return db_get_todo()Copy the code

You can also do this without using decorators

class Todo(Resource):
    def get(self, **kwargs):
        data = db_get_todo()
        return marshal(data, resource_fields)Copy the code

Example:

The class used to simulate the data object to be returned
class User(object):
    def __init__(self, user_id, name, age):
        self.user_id = user_id
        self.name = name
        self.age = age

resoure_fields = {
        'uer_id': fields.Integer,
        'name': fields.String
    }

class Demo1Resource(Resource):
    @marshal_with(resoure_fields, envelope='data1')
    def get(self):
        user = User(1.'itcast'.12)
        return user

class Demo2Resource(Resource):
    def get(self):
        user = User(1.'itcast'.12)
        return marshal(user, resoure_fields, envelope='data2')Copy the code

4.2 User-defined JSON Is Returned

demand

You want the JSON data returned by the interface to have the following uniform format

{"message": "description ", "data": {specific data to return}}Copy the code

Message returns OK if the interface handles properly, but if you want each interface to return correctly, omit the Message field

class DemoResource(Resource):
    def get(self):
        return {'user_id':1.'name': 'admin'}Copy the code

Can an interface like this be uniformly formatted somewhere?

{"message": "OK"."data": {"user_id":1."name": "admin"}}Copy the code
The solution

Flask-restful Api objects provide a representation decorator that allows you to customize the presentation format of returned data

api = Api(app)

@api.representation('application/json')
def handle_json(data, code, headers):
    # TODO Add custom handling here
    return respCopy the code

Flask-restful Original processing of JSON format is as follows:

Source code: flask_restful. Representations. Json

from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps


def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    settings = current_app.config.get('RESTFUL_JSON', {})

    # If we're in debug mode, and the indent is not set, we set it to a
    # reasonable value here. Note that this won't override any existing value
    # that was set. We also set the "sort_keys" value.
    if current_app.debug:
        settings.setdefault('indent'.4)
        settings.setdefault('sort_keys'.not PY3)

    # always end the json dumps with a new line
    # see https://github.com/mitsuhiko/flask/pull/1262
    dumped = dumps(data, **settings) + "\n"

    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return respCopy the code

To meet the requirements, make the following changes:

@api.representation('application/json')
def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    # add *************** here for customization
    if 'message' not in data:
    data = {
        'message': 'OK'.'data': data
    }
    # * * * * * * * * * * * * * * * * * * * * * * * * * *

    settings = current_app.config.get('RESTFUL_JSON', {})

    # If we're in debug mode, and the indent is not set, we set it to a
    # reasonable value here. Note that this won't override any existing value
    # that was set. We also set the "sort_keys" value.
    if current_app.debug:
        settings.setdefault('indent'.4)
        settings.setdefault('sort_keys'.not PY3)

    # always end the json dumps with a new line
    # see https://github.com/mitsuhiko/flask/pull/1262
    dumped = dumps(data, **settings) + "\n"

    resp = make_response(dumped, code)
    resp.headers.extend(headers or {})
    return respCopy the code

5. Summary

Flask-restful: Flask-restful: Flask-restful: Flask-restful: Flask-restful: Flask-restful: Flask-restful