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)