RESTFul資料查詢

weixin_33912246發表於2018-09-22
App/init.py
from flask import Flask
from App.urls import init_api


def create_app():
    app = Flask(__name__)

    init_api(app)

    return app

App/urls.py
from flask_restful import Api
from App.apis import DemoResource, PersonResource, AddressResource, MovieResource

api = Api()

def init_api(app):
    api.init_app(app)


api.add_resource(DemoResource, '/demos/', '/hello/')
api.add_resource(PersonResource, '/persons/', endpoint='test') # 相當於反向解析
api.add_resource(AddressResource, '/addresses/<int:a_id>/')
api.add_resource(MovieResource, '/movies/')

App/api.py
from flask import request
from flask_restful import Resource, fields, marshal_with, reqparse

from App.ext import db
from App.models import Person, Address, Movie

demo_fileds = {
    'hello': fields.String,
    'status': fields.Integer,
    # 在這定義的key,客戶端必然會顯示.
    # 但是如果在返回值裡,沒有找到對應的key,客戶端收的到值是null
    'mmmm': fields.String,
    # 在這裡定義的key,如果返回值裡沒有這個欄位,客戶端會顯示default裡的值
    'ssss': fields.String(default='我是格式化裡的key,我有預設值'),
    # 相當於給 password 這個key起了一個別名 private_key
    'private_key': fields.String(attribute='password'),
    # test 是在呼叫api.add_resource()時指定的值
    # 可以理解為 127.0.0.0:5000/persons/ 路徑
    'url': fields.Url('test', absolute=True)
}


class DemoResource(Resource):
    @marshal_with(demo_fileds)
    def get(self):
        # hi 在返回的時候不顯示,因為使用demo_fields進行的格式化
        # 在demo_fileds裡沒有指定 hi 欄位
        return {'hello': 'world', 'status': 200, 'hi': 'xxxx', 'password': '123'}

    def post(self):
        return {'hi': '你好'}



#返回一條資料
# 對addr 進行格式化
addr_fields = {
    'a_shortname': fields.String,
    'a_province': fields.String,
    '省會': fields.String(attribute='a_capital')
}
data_fields = {
    'msg': fields.String,
    'status': fields.Integer,
    'data': fields.Nested(addr_fields)
}


class AddressResource(Resource):
    @marshal_with(data_fields)
    def get(self, a_id):
        addr = Address.query.get(a_id)
        return {'msg': 'ok', 'status': 200, 'data': addr}



# 最終版  返回多條資料
person_fields = {
    'p_name': fields.String,
    'p_province': fields.String
}

result_fileds = {
    'msg': fields.String,
    'status': fields.Integer,
    'data': fields.List(fields.Nested(person_fields))
}


class PersonResource(Resource):
    # 可以使用裝飾器來序列化
    @marshal_with(result_fileds, envelope='test')
    def get(self):
        persons = Person.query.all()
        return {'msg': '獲取成功', 'status': 200, 'data': persons}
        # return marshal({'msg': '獲取成功', 'status': 200, 'data': persons}, result_fileds)

引數解析

movie_fields = {
    'name': fields.String(attribute='m_name')
}
movie_result = {
    'msg': fields.String,
    'status': fields.Integer,
    'data': fields.Nested(movie_fields)
}

parser = reqparse.RequestParser()

# help 是一個提示資訊
# 1. 如果這個引數被標記為required,但是未傳入這個引數,會顯示提示資訊
# 2. 傳入了引數,但是引數的型別和規定的型別不匹配,會顯示提示資訊
parser.add_argument('m_id', type=int, help='缺少引數m_id', required=True)
parser.add_argument('m_name')
parser.add_argument('session', location='cookies')
parser.add_argument('User-Agent', location='headers')
parser.add_argument('hello', type=str, action='append')
# 相當於給我們的引數 ssss 重新定義了一個名字
parser.add_argument('ssss', type=str, dest='mmmm')


class MovieResource(Resource):
    @marshal_with(movie_result)
    def get(self):
        my_parse = parser.parse_args()

        # m_id = request.args.get('m_id')
        m_id = my_parse['m_id']
        print(my_parse['session'])
        print(my_parse['User-Agent'])
        print(my_parse['hello'])
        print(my_parse.get('mmmm'))
        movie = Movie.query.get(m_id)

        return {'msg': 'ok', 'status': 200, 'data': movie}

    @marshal_with(movie_result)
    def post(self):
        my_parse = parser.parse_args()
        # m_name = request.form.get('m_name')

        m_name = my_parse['m_name']
        movie = Movie()
        movie.m_name = m_name

        db.session.add(movie)
        db.session.commit()

        return {'msg': 'ok', 'status': 201, 'data': movie}

繼承(上面parse)

格式:父類名.copy()

user_parser = parser.copy()
user_parser.remove_argument('hello')
user_parser.add_argument('u_id')


class UserResource(Resource):
    def get(self):
        user_parser.parse_args()
        return {'msg': 'ok', 'status': 200}

總結

Flask-restful的使用

安裝
pip insall flask-restfull

使用

url.py
api = Api()
def init_api(app):
    api.init_app(app)

api.add_resource(DemoResource,'/demos/','/hello/')
api.add_resourc(PersonResource,'/person/<int:p_id>/')
api.add_resource(AddressResource,'/addresses/',endpoint='test')
api.add_resource(MovieResource,'/movies/')
     
api.py
class DemoResource(Resource):
    def get(self):
        return {'hello':'world','status':200,'hi':'xxxxx','password':'1234'}

返回JSON序列化

最簡單的資料結構
eg:
api.add_resource(PersonResource,'/person/',endpoint='test')

demo_fields = {
    'hello':fields.String,
    'status':fields.Integer,
    # 在這定義的key,客戶端必然會顯示
    # 但是如果返回值裡,沒有找到對應的key,客戶端收到的值是null
    'mmmm':fileds.String,
    # 在這裡定義的key,如果返回值裡沒有這個欄位,客戶端會顯示default裡的值
    # 相當於給 password 這個key起了一個別名 private_key
    'private_key':field.String(attribute='password')
    # test 是在呼叫api.add_resource()時指定的值
    # 可以理解為 127.0.0.1:5000/person/ 路徑
    'url':fields.Url('test',absolute=True)

}
     retrun  {'hello':'hehe','status':200,'passwrod':'abcd1234'}  #伺服器的返回結果

    {'hello':'hehe','status':200,'mmmm':null,'ssss':'我是格式化裡的key,我有預設值','private_key':'abcd1234','url':'127.0.0.1:5000/persons/'} 

返回一個物件

addr_fields = {
    'a_shortname':fields.String,
    'a_province':fields.String,
    '省會':fields.String(attribute='a_capital')
}
data_fields = {
    'msg':fields.String,
    'status':fields.Integer,
    'data':fields.Nested(addr_fields)
}
    return {'msg':'ok','status':200,'data':addr} # 伺服器返回的資料
    {'msg':ok,'status':200,'data':{'a_shortname':'鄂','a_province':'湖北','省會':'武漢'}} # 客戶端返回的資料

返回一個列表,裡面有很多資料

person_fields = {
    'p_name':fields.String,
    'p_province':fields.String
}
result_fields = {
    'msg':fields.String,
    'status':fields.Integer,
    'data':fields.List(fields.Nested(person_fields))
}

{'msg':'ok','status':200,'data':persons}
json = {'msg':'ok','status':200,'data':[
    {'p_name':'zhangsan','p_province':'湖北'},
    {'p_name':'李四','p_province':'河北'},
    {'p_name':'王五','p_province':'海南'}
    ]}
json.data[1]['p_name']   # 拿一個人的名字: 李四

引數解析

perser = reqparse.RequestParser()
 # help  是一個提示資訊
# 1. 如果這個引數被標記為required,但是未傳入這個引數,會顯示提示資訊
# 2.傳入引數,但是引數的型別和規定的型別不匹配,會顯示提示資訊
parser.add_argument('m_id',type=int,help='缺少引數m_id',required=True)
parser.add_argument('m_name')
parser.add_argument('session',location='cokies')
parser.add_argument('User_Agent',location='headers')
# 允許hello引數有多個值
parser.add_argument('hello',type=str,action='append')
# 相當於給我們的引數 ssss 重新定義了一個名字
parser.add_argument('ssss',type=str,dest='mmmm')

class MovieResource(Resource):
    @marshal_with(movie_result)
    def get(self):
        my_parse = parser.parse_args()
        # m_id = request.args.get('m_id')
        m_id = my_parse['m_id']
        print(my_parse['session'])
        print(my_parse['User-Agent'])
        # 如果傳入的引數裡多個hello,可以把所有的hello的值拿出來
        print(my_parse.get('mmmm'))
        movie = Movie.query.get(m_id)
12529562-7ab73e83a1e15cae.png

相關文章