Skip to content

Commit 96a96db

Browse files
committed
add swagger documentation to api
1 parent f42139b commit 96a96db

File tree

6 files changed

+87
-50
lines changed

6 files changed

+87
-50
lines changed

.env

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# docker-compose config
2-
WEB_PORT=80
1+
VERSION=0.7
32

3+
WEB_PORT=80
44
APP_PORT=5000
55

66
DB_NAME=company

README.md

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## Quick start
2+
3+
```shell
4+
$ docker-compose up
5+
```
6+
Connect **http://localhost/api**
7+
18
## How to develop
29

310
```shell
@@ -18,8 +25,8 @@ app$ DEBUG=1 python $PWD/app.py
1825
```shell
1926
$ curl -i -X GET http://localhost:5000/api/company?name=Agi
2027
$ curl -i -X GET http://localhost:5000/api/company?tag=tag_26
21-
$ curl -i -X PUT -H "Content-Type: application/json" -d '{"name": "infobank", "language": "en", "tag": "tag_5"}' http://localhost:5000/api/company
22-
$ curl -i -X DELETE -H "Content-Type: application/json" -d '{"name": "infobank", "language": "en", "tag": "tag_5"}' http://localhost:5000/api/company
28+
$ curl -i -X PUT -H "Content-Type: application/json" -d '{"language": "en", "name": "infobank", "tag": "tag_5"}' http://localhost:5000/api/company
29+
$ curl -i -X DELETE -H "Content-Type: application/json" -d '{"language": "en", "name": "infobank", "tag": "tag_5"}' http://localhost:5000/api/company
2330
```
2431

2532
## How to run

app/app.py

+54-31
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
from flask import Flask, request, jsonify, abort
2-
from flask_restful import Api,Resource
3-
from functools import wraps
4-
from config import SQLALCHEMY_DATABASE_URI, SECRET_KEY
1+
from flask import Flask, jsonify, abort
2+
from flask_restx import Api, Resource, reqparse
3+
from config import VERSION, SQLALCHEMY_DATABASE_URI, SECRET_KEY
54
from models import db, Company, Language, CompanyName, CompanyTag
65

76

@@ -12,28 +11,45 @@
1211
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
1312

1413
db.init_app(app)
15-
api = Api(app)
14+
api = Api(app,
15+
version=VERSION, title='Company API',
16+
description='A company name & tag API',
17+
doc='/api')
1618

1719

18-
def check_name_language(func):
19-
@wraps(func)
20-
def wrapper(*args, **kwargs):
21-
return func(*args, **kwargs)
20+
read_parser = reqparse.RequestParser()
21+
read_parser.add_argument('name', type=str, location='args', help='Company Name')
22+
read_parser.add_argument('tag', type=str, location='args', help='Company Tag')
2223

23-
return wrapper
24+
write_parser = reqparse.RequestParser()
25+
write_parser.add_argument('language', required=True,
26+
type=str, location='json', help='Country Code')
27+
write_parser.add_argument('name', required=True,
28+
type=str, location='json', help='Company Name')
29+
write_parser.add_argument('tag', required=True,
30+
type=str, location='json', help='Company Tag')
2431

2532

33+
@api.route('/api/company')
2634
class ApiCompany(Resource):
35+
@api.expect(read_parser)
36+
@api.doc(responses={
37+
200: 'Success',
38+
400: 'Validation Error'
39+
})
2740
def get(self):
28-
name = request.args.get('name')
41+
args = read_parser.parse_args()
42+
print(args)
43+
44+
name = args['name']
2945
if name:
3046
company_name = CompanyName.query \
3147
.filter(CompanyName.name.like('%{}%'.format(name))) \
3248
.first()
3349
if company_name:
3450
return company_name.name
3551

36-
tag = request.args.get('tag')
52+
tag = args['tag']
3753
if tag:
3854
companies = Company.query \
3955
.join(CompanyTag) \
@@ -51,14 +67,20 @@ def get(self):
5167
print(results)
5268
return jsonify(results)
5369

70+
abort(status=400, description='No arguments')
71+
72+
@api.expect(write_parser)
73+
@api.doc(responses={
74+
200: 'Success',
75+
400: 'Validation Error'
76+
})
5477
def put(self):
55-
req_data = request.get_json()
56-
if req_data is None or any(key not in req_data for key in ('name', 'language', 'tag')):
57-
abort(status=400, description='Invalid request data')
78+
args = write_parser.parse_args()
79+
print(args)
5880

59-
name = req_data['name']
60-
country_code = req_data['language']
61-
tag = req_data['tag']
81+
country_code = args['language']
82+
name = args['name']
83+
tag = args['tag']
6284

6385
company_names = CompanyName.query \
6486
.filter_by(name=name) \
@@ -76,7 +98,7 @@ def put(self):
7698
db.session.commit()
7799
print('language', language.id)
78100

79-
results = {'updated': []}
101+
results = {'Updated': []}
80102
for company_name in company_names:
81103
company_tag = CompanyTag.query \
82104
.filter_by(
@@ -91,19 +113,23 @@ def put(self):
91113
db.session.commit()
92114
print('company_tag', company_tag.id)
93115

94-
results['updated'].append({name: tag})
116+
results['Updated'].append({name: tag})
95117

96118
print(results)
97119
return jsonify(results)
98120

121+
@api.expect(write_parser)
122+
@api.doc(responses={
123+
200: 'Success',
124+
400: 'Validation Error'
125+
})
99126
def delete(self):
100-
req_data = request.get_json()
101-
if req_data is None or any(key not in req_data for key in ('name', 'language', 'tag')):
102-
abort(status=400, description='Invalid request data')
127+
args = write_parser.parse_args()
128+
print(args)
103129

104-
name = req_data['name']
105-
country_code = req_data['language']
106-
tag = req_data['tag']
130+
country_code = args['language']
131+
name = args['name']
132+
tag = args['tag']
107133

108134
company_names = CompanyName.query \
109135
.filter_by(name=name) \
@@ -121,7 +147,7 @@ def delete(self):
121147
db.session.commit()
122148
print('language', language.id)
123149

124-
results = {'deleted': []}
150+
results = {'Deleted': []}
125151
for company_name in company_names:
126152
company_tag = CompanyTag.query \
127153
.filter_by(
@@ -135,14 +161,11 @@ def delete(self):
135161
db.session.commit()
136162
print('company_tag', company_tag.id)
137163

138-
results['deleted'].append({name: tag})
164+
results['Deleted'].append({name: tag})
139165

140166
print(results)
141167
return jsonify(results)
142168

143169

144-
api.add_resource(ApiCompany, '/api/company')
145-
146-
147170
if __name__ == '__main__':
148171
app.run(host='0.0.0.0', debug=True)

app/config.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import os
22

33
if 'DEBUG' in os.environ:
4-
print('[Debug] Local debug mode')
4+
print('[Debug] development mode')
55

66
from dotenv import load_dotenv
77

@@ -10,7 +10,10 @@
1010
load_dotenv(dotenv_path=env_path)
1111

1212
os.environ['DB_SERVER'] = '127.0.0.1'
13+
else:
14+
print('[Debug] production mode')
1315

16+
VERSION = os.environ['VERSION']
1417
SECRET_KEY = os.environ['SECRET_KEY']
1518
DB_USER = os.environ['DB_USER']
1619
DB_PASS = os.environ['DB_PASS']

app/requirements.txt

+6-3
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
1-
alembic==1.5.4
1+
alembic==1.5.5
22
aniso8601==9.0.0
3+
attrs==20.3.0
34
autopep8==1.5.4
45
certifi==2020.12.5
56
click==7.1.2
67
Flask==1.1.2
78
Flask-Migrate==2.6.0
8-
Flask-RESTful==0.3.8
9+
flask-restx==0.2.0
910
Flask-Script==2.0.6
1011
Flask-SQLAlchemy==2.4.4
1112
itsdangerous==1.1.0
1213
Jinja2==2.11.3
14+
jsonschema==3.2.0
1315
Mako==1.1.4
1416
MarkupSafe==1.1.1
1517
numpy==1.20.1
1618
pandas==1.2.2
1719
psycopg2-binary==2.8.6
1820
pycodestyle==2.6.0
21+
pyrsistent==0.17.3
1922
python-dateutil==2.8.1
2023
python-dotenv==0.15.0
2124
python-editor==1.0.4
2225
pytz==2021.1
2326
six==1.15.0
2427
SQLAlchemy==1.3.23
2528
toml==0.10.2
26-
Werkzeug==1.0.1
29+
Werkzeug==0.16.1

docker-compose.yml

+12-11
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ services:
1414
- ./nginx/nginx.conf.template:/etc/nginx/nginx.conf.template:ro
1515
- ./nginx/run_nginx.sh:/opt/nginx/run_nginx.sh
1616
ports:
17-
- ${WEB_PORT}:80
17+
- $WEB_PORT:80
1818
environment:
1919
- NGINX_PORT=80
2020
- APP_SERVICE=project-app
@@ -25,21 +25,22 @@ services:
2525

2626
app:
2727
container_name: project-app
28-
image: project_app:0.3
28+
image: project_app:$VERSION
2929
build:
3030
context: app/
3131
dockerfile: Dockerfile
3232
networks:
3333
- project_net
3434
ports:
35-
- ${APP_PORT}:5000
35+
- $APP_PORT:5000
3636
environment:
37-
- DB_USER=${DB_USER}
38-
- DB_PASS=${DB_PASS}
37+
- VERSION=$VERSION
38+
- DB_USER=$DB_USER
39+
- DB_PASS=$DB_PASS
3940
- DB_SERVER=project-db
4041
- DB_PORT=5432
41-
- DB_NAME=${DB_NAME}
42-
- SECRET_KEY=${SECRET_KEY}
42+
- DB_NAME=$DB_NAME
43+
- SECRET_KEY=$SECRET_KEY
4344
volumes:
4445
- ./db/:/opt/project/db/
4546
command: /bin/bash -c "./wait-for-postgres.sh db 5432 && ./migrate.sh /opt/project/db/migrations/ && python app.py"
@@ -52,10 +53,10 @@ services:
5253
networks:
5354
- project_net
5455
ports:
55-
- ${DB_PORT}:5432
56+
- $DB_PORT:5432
5657
environment:
57-
- POSTGRES_PASSWORD=${DB_PASS}
58-
- POSTGRES_USER=${DB_USER}
59-
- POSTGRES_DB=${DB_NAME}
58+
- POSTGRES_PASSWORD=$DB_PASS
59+
- POSTGRES_USER=$DB_USER
60+
- POSTGRES_DB=$DB_NAME
6061
volumes:
6162
- ./db/data/:/var/lib/postgresql/data/

0 commit comments

Comments
 (0)