Skip to content

Commit 4a1a4c8

Browse files
committed
Merge branch 'release/flask_example_v2.2'
2 parents 2634640 + 2120daf commit 4a1a4c8

File tree

10 files changed

+181
-14
lines changed

10 files changed

+181
-14
lines changed

README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@ Using Flask to build a Restful API Server with Swagger document.
55
Integration with Flask-restplus, Flask-Cors, Flask-Testing, Flask-SQLalchemy,and Flask-OAuth extensions.
66

77
### Extension:
8-
- Restful: Flask-restplus
8+
- Restful: [Flask-restplus](http://flask-restplus.readthedocs.io/en/stable/)
99

10-
- SQL ORM: Flask-SQLalchemy
10+
- SQL ORM: [Flask-SQLalchemy](http://flask-sqlalchemy.pocoo.org/2.1/)
1111

12-
- Testing: Flask-Testing
12+
- Testing: [Flask-Testing](http://flask.pocoo.org/docs/0.12/testing/)
13+
14+
- OAuth: [Flask-OAuth](https://pythonhosted.org/Flask-OAuth/)
15+
16+
- ESDAO: [elasticsearch](https://elasticsearch-py.readthedocs.io/en/master/) , [elasticsearch-dsl](http://elasticsearch-dsl.readthedocs.io/en/latest/index.html)
1317

14-
- OAuth: Flask-OAuth
1518

1619
## Installation
1720

@@ -86,9 +89,15 @@ JSON_SORT_KEYS : By default Flask will serialize JSON objects in a way that the
8689
- [reference¶](http://flask.pocoo.org/docs/0.12/config/)
8790

8891

89-
#### OAuth setup
92+
### OAuth Setup
9093
add your `client_id` and `client_secret` into config file.
9194

95+
### ESDAO Setup
96+
add your `ES host` and `ES port` into config file
97+
98+
99+
100+
92101
## Run Flask
93102
### Run flask for develop
94103
```
@@ -128,14 +137,20 @@ Offical Website
128137
- [Flask restplus](http://flask-restplus.readthedocs.io/en/stable/)
129138
- [Flask-SQLalchemy](http://flask-sqlalchemy.pocoo.org/2.1/)
130139
- [Flask-OAuth](https://pythonhosted.org/Flask-OAuth/)
140+
- [elasticsearch-dsl](http://elasticsearch-dsl.readthedocs.io/en/latest/index.html)
141+
- [gunicorn](http://gunicorn.org/)
131142

132143
Tutorial
133144

134145
- [Flask Overview](https://www.slideshare.net/maxcnunes1/flask-python-16299282)
135146
- [In Flask we trust](http://igordavydenko.com/talks/ua-pycon-2012.pdf)
136147

148+
[Wiki Page](https://github.com/tsungtwu/flask-example/wiki)
149+
150+
137151

138152
## Changelog
153+
- Version 2.2 : add ESDAO module
139154
- Version 2.1 : add OAuth extension: FLASK-OAuth, and google oauth example
140155
- Version 2.0 : add SQL ORM extension: FLASK-SQLAlchemy
141156
- Version 1.1 : update nosetest

webapp/app/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ def create_app(flask_config_name=None):
4545

4646
from app.model.userModel import User
4747

48-
me = User('admin', '[email protected]',None, None)
48+
me = User('admin', '[email protected]', None, None)
4949
daoPool.sqlDAO.session.add(me)
5050
daoPool.sqlDAO.session.commit()
5151

webapp/app/api/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
from app.api.cve.apiController import api as ns1
44
from app.api.user.apiController import api as ns2
55
from app.api.oauth.apiController import api as ns3
6+
from app.api.es.apiController import api as ns4
67

78

8-
api = Api(version='2.1', \
9+
api = Api(version='2.2', \
910
title='Flask Restful plus Api', \
1011
doc='/api', \
1112
description='Document for Restful api', \
@@ -16,3 +17,4 @@
1617
api.add_namespace(ns1, path='/api/cves')
1718
api.add_namespace(ns2, path='/api/users')
1819
api.add_namespace(ns3, path='/api/oauth')
20+
api.add_namespace(ns4, path='/api/es')

webapp/app/api/es/__init__.py

Whitespace-only changes.

webapp/app/api/es/apiController.py

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# -*- coding: utf-8 -*-
2+
import json, re
3+
import os
4+
5+
from flask_restplus import reqparse, Resource, Api, fields, Namespace, abort
6+
from flask import request, session, make_response, redirect, Response
7+
from elasticsearch_dsl import Q, A, Search
8+
9+
from app.util.regToolBox import RegToolBox
10+
from app.util.exceptionHandler import ExcepitonHandler
11+
from app.dao import daoPool
12+
13+
14+
api = Namespace('es', description='Es operation')
15+
esDAO = daoPool.esDAO
16+
17+
regBox = RegToolBox()
18+
excpHandler = ExcepitonHandler()
19+
20+
21+
## Request parsing
22+
parser = reqparse.RequestParser()
23+
parser.add_argument('from', type=int, required=True, help='Offset from the first result')
24+
parser.add_argument('size', type=int, required=True, help='Amount of cve item to be returned')
25+
26+
parserAgg = reqparse.RequestParser()
27+
parserAgg.add_argument('size', type=int, required=True, help='Number of item to be returned')
28+
29+
@api.route('/search')
30+
class GoogleLogin(Resource):
31+
"""google resource"""
32+
def __init__(self, Resource):
33+
self.api = api
34+
esDAO.setIndexAndType("cve", "detail")
35+
36+
37+
@api.expect(parser)
38+
@api.doc(description='ESDAO Search example')
39+
def get(self):
40+
""" Return es result """
41+
args = parser.parse_args()
42+
43+
size = args['size']
44+
fromOffset = args['from']
45+
46+
q = Q()
47+
sortQ = {}
48+
49+
result = {}
50+
resultList = []
51+
resp = esDAO.search(q, sortQ, fromOffset, size)
52+
53+
for hit in resp.to_dict()['hits']['hits']:
54+
resultList.append(hit)
55+
56+
result['result'] = resultList
57+
58+
return result
59+
60+
@api.route('/aggs')
61+
class EsAggs(Resource):
62+
""" """
63+
def __init__(self, Resource):
64+
self.api = api
65+
esDAO.setIndexAndType("cve", "detail")
66+
67+
68+
@api.expect(parserAgg)
69+
@api.doc(description='ESDAO Aggregation example' \
70+
'Get top `size` recent item')
71+
def get(self):
72+
""" get top recent result """
73+
args = parserAgg.parse_args()
74+
75+
topSize = args['size']
76+
77+
q = Q()
78+
s = Search().query(q)
79+
sortDate = [{"original_release_date": {"order": "desc"}}]
80+
a_date = A('top_hits', sort=sortDate, size=topSize)
81+
s.aggs.metric('_topDate', a_date)
82+
83+
result = {}
84+
resultList = []
85+
resp = esDAO.aggs(s).to_dict()
86+
for hit in resp['_topDate']['hits']['hits']:
87+
resultList.append(hit)
88+
89+
result['_topDate'] = resultList
90+
91+
return result

webapp/app/config.Development.cfg

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ JSON_AS_ASCII = 'false'
88
SECRET_KEY = 'f5557d4fcf727a981a3c315aca733eefa2996f7c7cdae1fa7e0de28522820bb0'
99

1010
## Elasticsearch settings
11-
#ELASTICSEARCH_HOST = ''
12-
#ELASTICSEARCH_PORT = '9200'
11+
ELASTICSEARCH_HOST = ''
12+
ELASTICSEARCH_PORT = '9200'
13+
1314

1415
## CORS settings
1516
CORS_ORIGIN = '*'

webapp/app/config.Production.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ TESTING = False
66
JSON_AS_ASCII = 'false'
77

88
#elasticsearch settings
9-
#ELASTICSEARCH_HOST = ''
10-
#ELASTICSEARCH_PORT = '9200'
9+
ELASTICSEARCH_HOST = ''
10+
ELASTICSEARCH_PORT = '9200'
1111

1212
#CORS settings
1313
CORS_ORIGIN = '*'

webapp/app/config.Testing.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ TESTING = True
66
JSON_AS_ASCII = 'false'
77

88
#elasticsearch settings
9-
#ELASTICSEARCH_HOST = ''
10-
#ELASTICSEARCH_PORT = '9200'
9+
ELASTICSEARCH_HOST = ''
10+
ELASTICSEARCH_PORT = '9200'
1111

1212

1313

webapp/app/dao/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
from flask_sqlalchemy import SQLAlchemy
22
from app.model import init_model
3-
3+
from app.dao.esDAO import ElasticsearchDAO
44

55
class DaoPool():
6+
67
sqlDAO = None
8+
esDAO = None
79
def __init__(self):
810
pass
911

@@ -13,4 +15,7 @@ def init_app(self, app):
1315
self.sqlDAO = SQLAlchemy(app)
1416
init_model(self.sqlDAO)
1517

18+
self.esDAO = ElasticsearchDAO(app.config['ELASTICSEARCH_HOST'], \
19+
app.config['ELASTICSEARCH_PORT'])
20+
1621
daoPool = DaoPool()

webapp/app/dao/esDAO.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import sys
2+
import datetime
3+
import logging
4+
from elasticsearch import Elasticsearch
5+
from flask_restplus import reqparse, Resource
6+
from elasticsearch_dsl import Search, Q, A
7+
8+
9+
reload(sys)
10+
sys.setdefaultencoding('utf-8')
11+
logger = logging.getLogger('ESDAO')
12+
class ElasticsearchDAO():
13+
client = None
14+
indexES = None
15+
typeES = None
16+
esearch = None
17+
def __init__(self, host, port):
18+
url = "%s:%s" % (host, port)
19+
try:
20+
self.client = Elasticsearch([url], send_get_body_as="POST")
21+
except:
22+
logger.error('elasticsearch cannot connect')
23+
24+
def setIndexAndType(self, index, type):
25+
self.indexES = index
26+
self.typeES = type
27+
self.esearch = Search(using=self.client, index=self.indexES, doc_type=self.typeES)
28+
29+
30+
def saveJson(self, json):
31+
"""put json to ES """
32+
res = self.client.index(index=self.indexES, doc_type=self.typeES, body=json)
33+
return res
34+
35+
36+
def aggs(self, searchQuery):
37+
s = self.esearch.query()
38+
s.aggs = searchQuery.aggs
39+
s.query = searchQuery.query
40+
s = s[0:0]
41+
response = s.execute()
42+
43+
return response.aggregations
44+
45+
def search(self, q, sortQ, fromOffset, size):
46+
s = self.esearch.query(q) \
47+
.sort({"_score":{"order":"desc"}}, sortQ)
48+
s = s[fromOffset:fromOffset+size]
49+
response = s.execute()
50+
51+
return response
52+
53+

0 commit comments

Comments
 (0)