I am playing a little bit with Google App Engine (GAE) and as first thing I tried to integrate OpenUI5 in a demo app.
My app is just showing a list of projects and let the user to create a new project.
Here a screen:
Detailed info for Google App Engine SDK installation can be found in the official documentation:
Download the Google App Engine SDK - Google App Engine — Google Developers
I also used PyDev eclipse plugin as IDE.
For OpenUI5 SDK, you can download it from here (I used version 1.22.4):
On App Engine side, my application is built on three main python modules:
models/project.py --> it is the model; it creates one Datastore entity - Projects - with two characteristics: project_id and project_description and it implements three functions:
- get_projects: returns all created projects
- get_project: returns one single project
- put_project: creates a new project
from google.appengine.ext import db class Projects(db.Model): project_id = db.StringProperty(required=True, ) project_description = db.StringProperty(required=True) def get_projects(): list_of_projects = [] q = db.GqlQuery("SELECT * FROM Projects") for p in q.run(): current_project = { 'project_id' : p.project_id, 'project_description' : p.project_description} list_of_projects.append(current_project) return list_of_projects def get_project(project_id=None): if not project_id: return None key = db.Key.from_path('Projects', project_id) project = db.get(key) if not project: return None return project def put_project(project_id, project_description): query = Projects.all(keys_only=True).filter('project_id', project_id) entity = query.get() if entity: raise Exception('unique_property must have a unique value!') project = Projects(project_id=project_id, project_description=project_description) project.put()
main.py --> Is the main request handler for the GAE application (MainPage class is the handler)
import datetime import jinja2 import os import webapp2 from google.appengine.api import users template_env = jinja2.Environment( loader=jinja2.FileSystemLoader(os.getcwd())) class MainPage(webapp2.RequestHandler): def get(self): current_time = datetime.datetime.now() current_user = users.get_current_user() login_url = users.create_login_url(self.request.path) logout_url = users.create_logout_url(self.request.path) template = template_env.get_template('templates/index.html') context = { 'current_time' : current_time, 'current_user' : current_user, 'login_url' : login_url, 'logout_url' : logout_url, } self.response.out.write(template.render(context)) application = webapp2.WSGIApplication([('/', MainPage)], debug=True)
projects_handler.py --> is the handler for a POST request to create a new project and a GET request to get all projects in a JSON format (I haven't found a good solution to espose the data via odata in python, some comments here would be really appreciated)
import webapp2 import json from models import projects class PostProject(webapp2.RequestHandler): def post(self): try: project_id = self.request.get('project_id') project_description = self.request.get('project_description') projects.put_project(project_id, project_description) except: self.response.set_status(500) return self.response.set_status(200) class GetProjects(webapp2.RequestHandler): def get(self): self.response.headers['Content-Type'] = 'application/json' obj = projects.get_projects() self.response.out.write(json.dumps(obj)) application = webapp2.WSGIApplication([('/post_project', PostProject)], debug=True) application_get_projects = webapp2.WSGIApplication([('/get_projects', GetProjects)], debug=True)
app.yaml is the GAE configuration file in python, I defined 4 static handlers for directories and three script handlers for the http requests (one for main page GET, one for GET the list of projects as Json file, one for POST a new project):
application: com-oloconsulting-damien version: 1 runtime: python27 api_version: 1 threadsafe: true handlers: - url: /css static_dir: css - url: /js static_dir: js - url: /openui5 static_dir: openui5-runtime-1.22.4 - url: /ui static_dir: ui - url: /post_project script: projects_handler.application - url: /get_projects script: projects_handler.application_get_projects - url: .* script: main.application libraries: - name: webapp2 version: "2.5.1" - name: jinja2 version: latest - name: markupsafe version: latest
Basically the app is working in this way: first page is managed by main.py, POST and GET requests on Projects model are managed by module projects_handler.py.
From OpenUI5 side, I created two views and put them in the same page:
ProjectList view (it implements a table for the list of projects):
sap.ui.jsview('ui.ProjectList', { getControllerName : function() { return 'ui.ProjectList'; }, createContent : function(oController) { var oTable = new sap.ui.table.Table({editable:false}); var oControl = new sap.ui.commons.TextView({text: '{project_id}'}); oTable.addColumn(new sap.ui.table.Column({ label: new sap.ui.commons.Label({text: oBundle.getText('ProjectId')}), template: oControl, sortProperty: 'project_id', filterProperty: 'project_id', width: '50px'})); var oControl = new sap.ui.commons.TextView({text: '{project_description}'}); oTable.addColumn(new sap.ui.table.Column({ label: new sap.ui.commons.Label({text: oBundle.getText('ProjectDescription')}), template: oControl, sortProperty: 'project_description', filterProperty: 'project_description', width: '200px'})); var aData = oController.getProjects(); var oModel = new sap.ui.model.json.JSONModel(); oModel.setData({modelData: aData}); oTable.setModel(oModel); oTable.bindRows('/modelData'); oTable.sort(oTable.getColumns()[0]); return oTable; } });
The controller is implementing only one function to get the list of the projects (it is called in the view to fill the model data: var aData = oController.getProjects();)
getProjects: function() { var aUrl = '/get_projects'; var aData = []; jQuery.ajax({ url: aUrl, async: false, type: 'GET', success: function(data, textStatus, jqXHR) { //alert('success to post'); aData = data; }, error: function(jqXHR, textStatus, errorThrown) { alert('fail to post'); } }); return aData; }
ProjectCreation view (it defines a form with a couple of textFields and a button):
sap.ui.jsview('ui.ProjectCreation', { getControllerName : function() { return 'ui.ProjectCreation'; }, createContent : function(oController) { var oLayout = new sap.ui.layout.form.GridLayout('ProjectCreationFormLayout'); var oForm = new sap.ui.layout.form.Form('ProjectCreationForm',{ title: new sap.ui.core.Title({ text: oBundle.getText('CreateProject') }), width: '50%', layout: oLayout, formContainers: [ new sap.ui.layout.form.FormContainer('ProjectCreationFC', { formElements: [ new sap.ui.layout.form.FormElement({ fields: [ new sap.ui.commons.Label('lblProjectId', { text: oBundle.getText('ProjectId') }), new sap.ui.commons.TextField('txtProjectId') ] }), new sap.ui.layout.form.FormElement({ fields: [ new sap.ui.commons.Label('lblProjectDescription', { text: oBundle.getText('ProjectDescription') }), new sap.ui.commons.TextField('txtProjectDescription') ] }), new sap.ui.layout.form.FormElement({ fields: [ new sap.ui.commons.Button('ProjectCreationButton', { text: 'Insert', tooltip: oBundle.getText('CreateProject'), press: function(oEvent){ oController.onCreateButtonPress(oEvent,oController); } }) ] }) ] }) ] }); return oForm; } });
The controller is implementing the function for inserting a new project:
onCreateButtonPress: function(oEvent, oController) { var oProjectId = sap.ui.getCore().byId('txtProjectId'); var oProjectDescription = sap.ui.getCore().byId('txtProjectDescription'); var aUrl = '/post_project'; var formData = { project_id: oProjectId.getValue(), project_description: oProjectDescription.getValue() }; jQuery.ajax({ url: aUrl, type: 'POST', data: formData, success: function(data, textStatus, jqXHR) { alert(oBundle.getText('ProjectCreationOk')); location.reload(); }, error: function(jqXHR, textStatus, errorThrown) { alert(oBundle.getText('ProjectCreationError')); } }); }
You can test the application at this link:
http://com-oloconsulting-damien.appspot.com/
here it is a snapshot of the GAE datastore after a couple of projects creation: