Skip to content

Commit

Permalink
Merge pull request #222 from strongbugman/feature/add_parsed_view
Browse files Browse the repository at this point in the history
Add "ParsedMethodView" and example
  • Loading branch information
javabrett committed Aug 27, 2018
2 parents 559764e + be670d6 commit aaef05c
Show file tree
Hide file tree
Showing 9 changed files with 539 additions and 120 deletions.
15 changes: 15 additions & 0 deletions examples/docs/item/get.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Get single item
---
tags:
- MethodView
parameters:
- name: id
type: integer
in: path
required: True
minimum: 1
responses:
200:
description: OK
schema:
$ref: '#/definitions/Item'
26 changes: 26 additions & 0 deletions examples/docs/item/put.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
Update single item
---
tags:
- MethodView
parameters:
- name: id
type: integer
in: path
required: True
minimum: 1
- name: Item
in: body
schema:
type: object
required:
- name
properties:
name:
type: string
maxLength: 31
description: global unique
responses:
200:
description: OK
schema:
$ref: '#/definitions/Item'
25 changes: 25 additions & 0 deletions examples/docs/items/get.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Get all items
---
tags:
- MethodView
parameters:
- name: type
type: string
in: query
required: True
maxLength: 10
responses:
200:
description: OK
schema:
$ref: '#/definitions/Items'
401:
description: Auth required
definitions:
Items:
type: object
properties:
objects:
type: array
items:
$ref: "#/definitions/Item"
25 changes: 25 additions & 0 deletions examples/docs/items/post.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
Create item
---
tags:
- MethodView
parameters:
- name: Item
in: body
schema:
type: object
required:
- name
- type
properties:
name:
type: string
maxLength: 31
description: global unique
type:
type: string
maxLength: 10
responses:
201:
description: OK
schema:
$ref: '#/definitions/Item'
16 changes: 16 additions & 0 deletions examples/docs/template.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
swagger: '2.0'
info:
title: 'Flasgger Parsed Method/Function View Example'
description: 'Example of swagger document auto loading by endpoint name(view function/method name), parsed by flask_restful.reqparse.RequestParser and validated by jsonschema'
version: '0.1'

definitions:
Item:
type: object
properties:
id:
type: integer
name:
type: string
type:
type: string
13 changes: 13 additions & 0 deletions examples/docs/user.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Get single user by id
---
tags:
- FunctionView
parameters:
- name: id
type: integer
in: query
required: True
minimum: 1
responses:
200:
description: OK
170 changes: 170 additions & 0 deletions examples/parsed_view_func.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
"""
Example of swagger document auto loading by endpoint
name(view function/method name), parsed by
flask_restful.reqparse.RequestParser and validated by jsonschema
"""
import os

from flask import Flask, request, jsonify, Response
from flask.views import MethodView
from flasgger import Swagger


app = Flask(__name__)
app.config['SWAGGER'] = {
'title': 'Flasgger Parsed Method/Function View Example',
'doc_dir': './examples/docs/'
}
swag = Swagger(
app,
template_file=os.path.join(
os.getcwd(), 'examples', 'docs', 'template.yml'),
parse=True)


class ItemsView(MethodView):
"""
Flasgger will try to load "./examples/docs/items/{method}.yml" as
swagger document
"""
def get(self):
"""
If we set "parse" is True in Flasgger app, we will get parsed and
validated data stored in "flask.request.parsed_data".
In "parsed_data", different location's var stored in different key,
there is a map between RequestParser's location and swagger
doc's "in" parameter, eg: 'query' -> 'args'.See
"Swagger.SCHEMA_LOCATIONS" for more locations
"""
return jsonify(
[{'name': 'test', 'id': 1, 'type': request.parsed_data['args']['type']},
{'name': 'test2', 'id': 2, 'type': request.parsed_data['args']['type']}])

def post(self):
return jsonify(
{'name': request.parsed_data['json']['name'], 'id': 3,
'type': request.parsed_data['json']['type']})


class ItemMethodView(MethodView):
def get(self, id):
return jsonify({'name': 'test', 'id': id, 'type': 'NORMAL'})

def put(self, id):
return jsonify(
{'name': request.parsed_data['json']['name'], 'id': 3, 'type': 'NORMAL'})


class EmptyView(MethodView):
"""In this view, we do not provide api doc"""
def get(self):
return Response(status=200)


@app.route('/api/users/<group>/', methods=['POST'])
def users(group):
"""Create one user with nested json body.
---
tags:
- FunctionView
parameters:
- name: group
in: path
type: string
required: true
- name: User
in: body
schema:
type: object
required:
- data
properties:
data:
type: object
required:
- name
- age
properties:
age:
type: integer
name:
type: string
definitions:
User:
type: object
properties:
id:
type: integer
name:
type: string
group:
type: string
age:
type: integer
responses:
200:
description: ok
schema:
$ref: '#/definitions/User'
examples:
{'id': 1, 'name': 'test', 'group': 1, 'age': 20}
400:
description: Miss data
"""
return jsonify(
{'id': 1,
'name': request.parsed_data['json']['data']['name'],
'age': request.parsed_data['json']['data']['age'],
'group': request.parsed_data['path']['group']})


@app.route('/api/user/')
def user():
"""Flasgger will try to load './examples/docs/user.yml' as swagger doc
"""
return jsonify({'id': request.parsed_data['args']['id'], 'name': 'test'})


app.add_url_rule(
'/api/items/', view_func=ItemsView.as_view(name='items'),
methods=['GET', 'POST'])
app.add_url_rule(
'/api/items/<int:id>/', view_func=ItemMethodView.as_view(name='item'),
methods=['GET', 'PUT'])
app.add_url_rule(
'/api/empty/', view_func=EmptyView.as_view(name='empty'),
methods=['GET'])


def test_swag(client, specs_data):
"""
This test is runs automatically in Travis CI
:param client: Flask app test client
:param specs_data: {'url': {swag_specs}} for every spec in app
"""
res = client.get('/api/items/')
assert res.status_code == 400
res = client.get('/api/items/?type=myLengthIsTooLong')
assert res.status_code == 400
res = client.get('/api/items/?type=NORMAL')

assert res.status_code == 200
res = client.get('/api/items/1/')
assert res.status_code == 200
res = client.put('/api/items/1/')
assert res.status_code == 400
res = client.put('/api/items/1/', json={'name': 'test'})
assert res.status_code == 200

res = client.post('/api/users/1/', json={'name': 'miss data'})
assert res.status_code == 400
res = client.post(
'/api/users/1/',
json={'data': {'name': 'test', 'age': 20}})
assert res.status_code == 200


if __name__ == '__main__':
app.run(debug=True)
Loading

0 comments on commit aaef05c

Please sign in to comment.