├── .gitignore ├── README.md ├── app ├── __init__.py ├── modules │ ├── Controller.py │ ├── Model.py │ └── __init__.py └── templates │ └── index.html ├── config.py ├── requirements.txt └── run.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | 4 | # Environments 5 | venv/ 6 | 7 | # PyCharm IDE 8 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | Hana to Python Application 3 | =================== 4 | 5 | The purpose of this project is to implement a simple Python application to demonstrate the integration between a common third party application to a SAP Hana database. 6 | 7 | > **Note:** 8 | > 9 | > - This project is directly linked to the project at the [HanaService](https://github.com/NickChecan/HanaService) repository. 10 | > - Project developed with Python 3.7. 11 | 12 | 13 | ---------- 14 | 15 | Project Components 16 | ------------- 17 | 18 | This project uses the [Flask](http://flask.pocoo.org/) framework to serve data through a simple web site platform locally. 19 | 20 | ``` 21 | HanaToPython-Application 22 | ├── app 23 | │ ├── modules 24 | │ │ ├── Controller.py 25 | │ │ ├── Model.py 26 | │ │ └── __init__.py 27 | │ ├── templates 28 | │ │ └── index.html 29 | │ └── __init__.py 30 | ├── config.py 31 | ├── requirements.txt 32 | └── run.py 33 | ``` 34 | 35 | The routes used in this application can be found at **./app/modules/Controller.py**. 36 | 37 | The **.app/modules/Model.py** file will be responsible to access the Hana data through a database connection established by the information provided at the **config.py** file. 38 | 39 | The template folder will handle all views available for the application. 40 | 41 | The file **requirements.txt** contains all the plugins used for the current application and the **run.py** file will be responsible for the application execution. 42 | 43 | 44 | ---------- 45 | 46 | Getting Started 47 | ------------- 48 | 49 | Before importing this project to your Python workspace, it is necessary to make sure the prerequisites steps are properly done in your development environment. 50 | The installation procedure described in this documentation will assume you've already have Python installed at your computer. 51 | 52 | #### Prerequisites 53 | 54 | - Hana Service
55 | To execute this application it will be necessary to properly deploy the [Hana Service](https://github.com/NickChecan/HanaService) project into your Hana Trial environment. 56 | 57 | - A Python Editor of your choice
58 | For this project the [PyCharm](https://www.jetbrains.com/pycharm/) IDE and [Visual Studio Code](https://code.visualstudio.com/) were used for development, but the same is not required to correctly deploy the application it self. 59 | 60 | - Install the virtual environment package
61 | **Virtual Environment** (virtualenv) is a tool to create isolated Python environments. The *virtualenv* command creates a folder which contains all the necessary executables to use the packages that a Python project would need. The same can be installed as described in [this link](http://docs.python-guide.org/en/latest/dev/virtualenvs/) through the following command: 62 | 63 | ``` 64 | $ pip install virtualenv 65 | ``` 66 | 67 | 68 | #### Installing 69 | 70 | The steps bellow will guide you through the project installation.
71 | The following commands should be executed in your computer console at the project folder: 72 | 73 | * Clone the project to your local repository workspace; 74 | 75 | * Create a virtual environment for the imported application through the following command: 76 | ``` 77 | $ virtualenv 78 | ``` 79 | * Activate your virtual environment with the command: 80 | ``` 81 | $ \Scripts\activate 82 | ``` 83 | * With the virtual environment properly activated, install the plugins available at the **requirements.txt** file through the command: 84 | ``` 85 | $ pip install -r requirements.txt 86 | ``` 87 | This process should enable your application to be deployed in a local server for test purpose. 88 | 89 | 90 | > **Note:** 91 | > 92 | > - With the [Hana Service](https://github.com/NickChecan/HanaService) properly deployed, the **config.py** file should be modified to attend the address of your Hana Trial Instance. 93 | 94 | 95 | ---------- 96 | 97 | Deployment 98 | ------------- 99 | 100 | With the Hana Service properly deployed, the **config.py** file modified to attend your Hana Trial Instance and the virtual environment activated, the python application should run through the following command: 101 | 102 | ``` 103 | $ python run.py 104 | ``` 105 | 106 | The same will enable the project to be accessed by you web browser trough a URL displayed by the mentioned command execution. 107 | 108 | > **Tips:** 109 | > 110 | > - As mentioned in the Hana Service project repository, always remember to make sure the Hana Trial Instance is up and running through the Cloud Platform Cockpit before execute commands or test any application directly linked to the Hana Service. 111 | 112 | 113 | 114 | Acknowledgments 115 | ------------- 116 | This project was made possible thanks to the Flask framework tutorials available at the [Tutorials Point](https://www.tutorialspoint.com/flask/) and at [Bruno Rocha](http://brunorocha.org/) personal blog. These two web sites was incredibly helpful in the development and preparation step of this project. 117 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/modules/Controller.py: -------------------------------------------------------------------------------- 1 | import json 2 | from flask import Blueprint 3 | from app.modules.Model import Model 4 | 5 | model = Model() 6 | controller = Blueprint('controller', "HanaToPython") 7 | 8 | 9 | @controller.route("/api/getRegions") 10 | def get_regions(): 11 | return json.dumps(model.get_regions), 200, {"Content-Type": "application/json"} 12 | 13 | 14 | @controller.route("/api/getProducts") 15 | def get_products(): 16 | return json.dumps(model.get_products), 200, {"Content-Type": "application/json"} 17 | 18 | 19 | @controller.route("/api/getSalesData") 20 | def get_sales_data(): 21 | return json.dumps(model.get_sales_data), 200, {"Content-Type": "application/json"} 22 | 23 | -------------------------------------------------------------------------------- /app/modules/Model.py: -------------------------------------------------------------------------------- 1 | import pyhdb 2 | from config import Hana 3 | 4 | 5 | class Model(object): 6 | 7 | connection = None 8 | 9 | def __init__(self): 10 | self.connection = pyhdb.connect(Hana.HOST, Hana.PORT, Hana.USER, Hana.PASS) 11 | 12 | @property 13 | def get_regions(self): 14 | regions_data = [] 15 | cursor = self.connection.cursor() 16 | cursor.execute("SELECT * FROM \"SALES_TUTORIAL\".\"HanaService.CDSScripts::SalesDDL.Region\"") 17 | result_set = cursor.fetchall() 18 | for result in result_set: 19 | regions_data.append({"regionId": result[0], 20 | "regionName": result[1], 21 | "subRegionName": str(result[2])}) 22 | return regions_data 23 | 24 | @property 25 | def get_products(self): 26 | products_data = [] 27 | cursor = self.connection.cursor() 28 | cursor.execute("SELECT * FROM \"SALES_TUTORIAL\".\"HanaService.CDSScripts::SalesDDL.Product\"") 29 | result_set = cursor.fetchall() 30 | for result in result_set: 31 | products_data.append({"productId": result[0], 32 | "productName": result[1]}) 33 | return products_data 34 | 35 | @property 36 | def get_sales_data(self): 37 | sales_data = [] 38 | cursor = self.connection.cursor() 39 | cursor.execute("SELECT * FROM \"_SYS_BIC\".\"HanaService/SalesData\"") 40 | result_set = cursor.fetchall() 41 | for result in result_set: 42 | sales_data.append({"regionName": result[0], 43 | "productName": result[1], 44 | "salesAmount": str(result[2])}) 45 | return sales_data 46 | 47 | -------------------------------------------------------------------------------- /app/modules/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickChecan/hana-to-python/49d8098a533a312851cc98efc28bb0ba85f28b27/app/modules/__init__.py -------------------------------------------------------------------------------- /app/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hana 2 Python 6 | 7 | 8 | 9 | 28 |
29 |

Hana data in a Python web application

30 |

This application uses common python/web frameworks. Gathering sales informations...

31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
Region NameProduct NameSales Amount
41 |

Try also or .

42 |
43 | 44 | -------------------------------------------------------------------------------- /config.py: -------------------------------------------------------------------------------- 1 | class DevelopmentConfig(object): 2 | DEBUG = True 3 | TESTING = False 4 | 5 | 6 | class Hana(object): 7 | HOST = "localhost" 8 | PORT = "00000" 9 | USER = "SYSTEM" 10 | PASS = "XXXXXX" 11 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | click==6.7 2 | flask>=0.12.3 3 | itsdangerous==0.24 4 | Jinja2>=2.10.1 5 | MarkupSafe==1.0 6 | pyhdb==0.3.3 7 | werkzeug>=0.15.3 8 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, render_template 2 | from app.modules.Controller import controller 3 | 4 | app = Flask("HanaToPython", template_folder='app/templates', instance_relative_config=True) 5 | app.register_blueprint(controller) 6 | app.config.from_object('config.DevelopmentConfig') 7 | 8 | 9 | @app.route("/") 10 | def home(): 11 | return render_template('index.html') 12 | 13 | if __name__ == '__main__': 14 | app.run(use_reloader=True) 15 | --------------------------------------------------------------------------------