Skip to content

Commit 581e964

Browse files
Initial commit
0 parents  commit 581e964

12 files changed

+360
-0
lines changed

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Python Mongodb Starter Pack
2+
3+
## Prerequisites
4+
1. Python 3.x
5+
2. Mongodb
6+
3. docker & docker-compose
7+
8+
## Configuration
9+
10+
Located under the yaml file.
11+
12+
- **MONGODB_URL** Mongodb connection url
13+
14+
the config value can be set through environment variable **MONGODB_URL**.
15+
16+
## Local Running
17+
18+
Go to app folder.
19+
20+
Install requirements:
21+
22+
```bash
23+
pip install -r requirements.txt
24+
```
25+
26+
Run application
27+
28+
```bash
29+
python app.py
30+
```
31+
32+
or override with environment variable
33+
34+
```bash
35+
MONGODB_URL=xxx python app.py
36+
```
37+
38+
39+
## Docker compose Running
40+
41+
Run:
42+
```bash
43+
docker-compose up --build
44+
```
45+
46+
47+
## Test and Verification
48+
49+
Import the postman collection in docs folder to test and verify.

app/Dockerfile

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
FROM python:3
2+
3+
4+
# Copy app
5+
COPY . /app
6+
7+
WORKDIR /app
8+
9+
10+
# Install dependenceis
11+
RUN pip install -r requirements.txt
12+
13+
# Expose port 5000
14+
EXPOSE 5000
15+
16+
# Run the server when container is launched
17+
CMD ["python", "app.py"]

app/app.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python
2+
from config import app
3+
from controllers.user_controller import api
4+
5+
# register the api
6+
app.register_blueprint(api)
7+
8+
if __name__ == '__main__':
9+
''' run application '''
10+
app.run(host='0.0.0.0', port=5000)

app/config.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python
2+
import os
3+
import yaml
4+
from flask import Flask
5+
from flask_mongoengine import MongoEngine
6+
7+
app = Flask(__name__)
8+
9+
config_obj = yaml.load(open('config.yaml'), Loader=yaml.Loader)
10+
11+
db_host = os.getenv('MONGODB_URL')
12+
13+
app.config['MONGODB_SETTINGS'] = {
14+
'host': config_obj['MONGODB_URL'] if db_host is None else db_host,
15+
}
16+
17+
18+
db = MongoEngine()
19+
20+
db.init_app(app)
21+

app/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
MONGODB_URL: 'mongodb://admin:[email protected]:27018/admin'

app/controllers/user_controller.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python
2+
from flask import Blueprint, jsonify, request
3+
import services.user_service as user_service
4+
from models.user import User
5+
from werkzeug.exceptions import HTTPException
6+
import json
7+
8+
api = Blueprint('users', 'users')
9+
10+
@api.route('/users', methods=['GET'])
11+
def api_get():
12+
''' Get all entities'''
13+
users = user_service.get()
14+
return jsonify([user.as_dict() for user in users])
15+
16+
@api.route('/users', methods=['POST'])
17+
def api_post():
18+
''' Create entity'''
19+
user = user_service.post(request.json)
20+
return jsonify(user.as_dict())
21+
22+
@api.route('/users/<string:id>', methods=['PUT'])
23+
def api_put(id):
24+
''' Update entity by id'''
25+
body = request.json
26+
body['id'] = id
27+
res = user_service.put(body)
28+
return jsonify(res.as_dict()) if isinstance(res, User) else jsonify(res)
29+
30+
@api.route('/users/<string:id>', methods=['DELETE'])
31+
def api_delete(id):
32+
''' Delete entity by id'''
33+
res = user_service.delete(id)
34+
return jsonify(res)
35+
36+
@api.errorhandler(HTTPException)
37+
def handle_exception(e):
38+
"""Return JSON format for HTTP errors."""
39+
# start with the correct headers and status code from the error
40+
response = e.get_response()
41+
# replace the body with JSON
42+
response.data = json.dumps({
43+
'success': False,
44+
"message": e.description
45+
})
46+
response.content_type = "application/json"
47+
return response

app/models/user.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#!/usr/bin/env python
2+
from config import db
3+
from bson.json_util import dumps
4+
import json
5+
6+
class User(db.Document):
7+
''' The data model'''
8+
handle = db.StringField(required=True)
9+
def as_dict(self):
10+
return {'id': json.loads(dumps(getattr(self,'pk')))['$oid'], 'handle': getattr(self, 'handle')}

app/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
PyYAML==5.1.2
2+
Flask==1.1.1
3+
flask-mongoengine==0.9.5

app/services/user_service.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#!/usr/bin/env python
2+
from models.user import User
3+
from config import db
4+
from werkzeug.exceptions import NotFound
5+
6+
def get():
7+
'''
8+
Get all entities
9+
:returns: all entity
10+
'''
11+
return User.objects()
12+
13+
def post(body):
14+
'''
15+
Create entity with body
16+
:param body: request body
17+
:returns: the created entity
18+
'''
19+
user = User(**body).save()
20+
return user
21+
22+
def put(body):
23+
'''
24+
Update entity by id
25+
:param body: request body
26+
:returns: the updated entity
27+
'''
28+
user = User.objects(pk=body['id']).first()
29+
if user:
30+
user.update(**body)
31+
return User(**body)
32+
raise NotFound('no such entity found with id=' + str(body['id']))
33+
34+
def delete(id):
35+
'''
36+
Delete entity by id
37+
:param id: the entity id
38+
:returns: the response
39+
'''
40+
user = User.objects(pk=id).first()
41+
if user:
42+
user.delete()
43+
return {'success': True}
44+
raise NotFound('no such entity found with id=' + str(id))
45+
46+

docker-compose.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
version: '2'
2+
services:
3+
database:
4+
image: mongo:3.4
5+
restart: always
6+
environment:
7+
MONGO_INITDB_ROOT_USERNAME: admin
8+
MONGO_INITDB_ROOT_PASSWORD: password
9+
app:
10+
build: app
11+
depends_on: [database]
12+
links:
13+
- database
14+
ports:
15+
- "5000:5000"
16+
environment:
17+
MONGODB_URL: 'mongodb://admin:password@database:27017/admin'
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
{
2+
"info": {
3+
"_postman_id": "857b96cd-b4ab-42e2-9068-58c20297baf0",
4+
"name": "Python-Starter",
5+
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
6+
},
7+
"item": [
8+
{
9+
"name": "Get",
10+
"request": {
11+
"method": "GET",
12+
"header": [],
13+
"url": {
14+
"raw": "{{url}}/users",
15+
"host": [
16+
"{{url}}"
17+
],
18+
"path": [
19+
"users"
20+
]
21+
}
22+
},
23+
"response": []
24+
},
25+
{
26+
"name": "Create",
27+
"event": [
28+
{
29+
"listen": "test",
30+
"script": {
31+
"id": "565d2574-1a1d-462e-a215-2069c432cbd8",
32+
"exec": [
33+
"var jsonData = pm.response.json();",
34+
"if (jsonData.id){",
35+
" pm.environment.set(\"id\", jsonData.id);",
36+
"}"
37+
],
38+
"type": "text/javascript"
39+
}
40+
}
41+
],
42+
"request": {
43+
"method": "POST",
44+
"header": [
45+
{
46+
"key": "Content-Type",
47+
"value": "application/json"
48+
}
49+
],
50+
"body": {
51+
"mode": "raw",
52+
"raw": "{\n\t\"handle\": \"tom\"\n}"
53+
},
54+
"url": {
55+
"raw": "{{url}}/users",
56+
"host": [
57+
"{{url}}"
58+
],
59+
"path": [
60+
"users"
61+
]
62+
}
63+
},
64+
"response": []
65+
},
66+
{
67+
"name": "PUT",
68+
"request": {
69+
"method": "PUT",
70+
"header": [
71+
{
72+
"key": "Content-Type",
73+
"value": "application/json"
74+
}
75+
],
76+
"body": {
77+
"mode": "raw",
78+
"raw": "{\n\t\"handle\": \"john7\"\n}"
79+
},
80+
"url": {
81+
"raw": "{{url}}/users/:id",
82+
"host": [
83+
"{{url}}"
84+
],
85+
"path": [
86+
"users",
87+
":id"
88+
],
89+
"variable": [
90+
{
91+
"key": "id",
92+
"value": "{{id}}"
93+
}
94+
]
95+
}
96+
},
97+
"response": []
98+
},
99+
{
100+
"name": "Delete",
101+
"request": {
102+
"method": "DELETE",
103+
"header": [],
104+
"url": {
105+
"raw": "{{url}}/users/:id",
106+
"host": [
107+
"{{url}}"
108+
],
109+
"path": [
110+
"users",
111+
":id"
112+
],
113+
"variable": [
114+
{
115+
"key": "id",
116+
"value": "{{id}}"
117+
}
118+
]
119+
}
120+
},
121+
"response": []
122+
}
123+
],
124+
"protocolProfileBehavior": {}
125+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"id": "61b87801-4312-499b-afc6-92211a98e462",
3+
"name": "Python-Starter",
4+
"values": [
5+
{
6+
"key": "url",
7+
"value": "localhost:5000",
8+
"enabled": true
9+
}
10+
],
11+
"_postman_variable_scope": "environment",
12+
"_postman_exported_at": "2019-10-20T10:42:47.301Z",
13+
"_postman_exported_using": "Postman/7.9.0"
14+
}

0 commit comments

Comments
 (0)