Code Your Application
Let’s begin coding the application.
Create the following files and directories to store your code:
- A Python code file in your project’s root directory (AlienCity/), name it “app.py”. This file will contain the backend logic for your application.
- A folder in your project’s root directory, name it “static”, and create the following files inside it (AlienCity/static/):
- index.html: Contains the HTML code for the frontend of the application
- main.js: Contains the JavaScript code of your application
This is the final folder structure of the AlienCity project:
You will be coding the app.py, index.html, and main.js files. You will also be updating the app-config.json file.
Note: Please go through the code in this section to make sure you fully understand it.
Copy the code below and paste it into the respective files of your project using an IDE and save the files.
app.pycopyimport sys sys.path.insert(0, './lib') from flask import Flask, request, jsonify import os import zcatalyst_sdk import logging tableName = 'AlienCity' # The table created in the Data Store columnName = 'CityName' app = Flask(__name__) @app.route('/') def index(): return app.send_static_file('index.html') @app.route('/alien', methods=['POST']) def post_alien_encounter(): try: logger = logging.getLogger() capp = zcatalyst_sdk.initialize(req=request) req_data = request.get_json() name = req_data.get('city_name') rowid = getAlienCountFromCatalystDataStore(request,name) # Queries the Catalyst Data Store table and checks whether a row is present for the given city if len(rowid) == 0: # If the row is not present, then a new row is inserted logger.info("Alien alert!") # Written to the logs. You can view this log from Logs under the Monitor section in the console datastore_service = capp.datastore() table_service = datastore_service.table(tableName) row_data = { columnName:name } table_service.insert_row(row_data) # Inserts the city name as a row in the Catalyst Data Store table return jsonify({ "message":"Thanks for reporting!!!" }),200 else: return jsonify({ "message": "Looks like you are not the first person to encounter aliens in this city! Someone has already reported an alien encounter here!" }), 200 except Exception as e: # If the row is present, then a message is sent indicating duplication print(e) return jsonify({ "message": "Internal server error" }), 500 @app.route('/alien', methods=['GET']) def get_alien_encounter(): try: name = request.args.get('city_name') rowid = getAlienCountFromCatalystDataStore(request,name) # Queries the Catalyst Data Store table and checks whether a row is present for the given city if len(rowid) == 0: return jsonify({ "message": "Hurray! No alien encounters in this city yet!", "signal": "negative" }), 200 else: return jsonify({ "message": "Uh oh! Looks like there are aliens in this city!", "signal": "positive" }), 200 except Exception as e: print(e) return jsonify({ "message": "Internal server error" }), 500 def getAlienCountFromCatalystDataStore(request,cityname): # Checks whether an alien encounter is already reported for the given city by querying the Data Store table capp = zcatalyst_sdk.initialize(req=request) zcql_service = capp.zcql() query = f"SELECT * FROM {tableName} WHERE {columnName} = {cityname}" output = zcql_service.execute_query(query) return output if __name__ == '__main__': port = int(os.environ.get('X_ZOHO_CATALYST_LISTEN_PORT', 9000)) app.run(host='0.0.0.0', port=port)
index.htmlcopy<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AlientCityAppClient</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"> </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"> </script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"> </script> <script src="static/main.js"> </script> </head> <body> <br> <br> <center> <h1>ALIEN CITY</h1> </center> <div class="container"> <ul class="nav nav-tabs" id="myTab" role="tablist"> <li class="nav-item"> <a class="nav-link active" id="check-tab" data-toggle="tab" href="#check" role="tab" aria-controls="check" aria-selected="true">Check My City</a> </li> <li class="nav-item"> <a class="nav-link" id="report-tab" data-toggle="tab" href="#report" role="tab" aria-controls="report" aria-selected="false">Report Alien Encounter</a> </li> </ul> <div class="tab-content" id="myTabContent"> <div class="tab-pane fade show active" id="check" role="tabpanel" aria-labelledby="check-tab"> <br> <br> <form> <div class="form-group"> <label for="city-get-input"> <b>Check if your city has aliens:</b> </label> <input type="text" class="form-control" id="city-get-input" aria-describedby="checkCity" placeholder="Enter City Name"> </div> <button type="submit" class="btn btn-primary" onclick="getAlienEncounter();return false;">Check</button> </form> <br> <br> <div id="result-container"> <div id="result-text"> </div> <br> <div id="result-image"> </div> </div> <div id="loader" style="display: none;"> <div class="spinner-border" role="status"> <span class="sr-only">Loading...</span> </div> </div> </div> <div class="tab-pane fade" id="report" role="tabpanel" aria-labelledby="report-tab"> <br> <br> <form> <div class="form-group"> <div class="city-post-input"> <label for="exampleInputEmail1"> <b>Enter the name of the city where you encountered an alien:</b> </label> <input type="text" class="form-control" id="city-post-input" aria-describedby="cityPost" placeholder="Enter City Name"> </div> </div> <button type="submit" class="btn btn-primary" onclick="postAlienEncounter();return false;">Report</button> </form> </div> </div> </div> </body> </html>
main.jscopyfunction postAlienEncounter() { debugger; var city = $("#city-post-input").val(); $.ajax({ url: "/alien", type: "post", contentType: "application/json", data: JSON.stringify({ "city_name": city }), success: function (data) { alert(data.message); }, error: function (error) { alert(error.message); } }); } function getAlienEncounter() { debugger showLoader(); var positive = "https://media.giphy.com/media/Y1GYiLui9NHcxVKhdo/giphy.gif"; var negative = "https://media.giphy.com/media/fsPcMdeXPxSP6zKxCA/giphy.gif"; var city = $("#city-get-input").val(); $.ajax({ url: "/alien?city_name=" + city, type: "get", success: function (data) { console.log(data); $("#result-text").text(""); $("#result-text").text(data.message); var imagesrc = negative; if (data.signal == 'positive') { imagesrc = positive; } $("#result-image").html(""); $("#result-image").html("<img src='" + imagesrc + "' />"); hideLoader(); }, error: function (error) { alert(error.message); } }); } function showLoader() { $("#result-container").hide(); $("#loader").show(); } function hideLoader() { $("#loader").hide(); $("#result-container").show(); }
Update the value of the key command as “python3 app.py” in the app-config.json file. This is the startup command that is specific for this programming stack and framework.
app-config.jsoncopy{ "command": "python3 app.py", "buildPath": "/Users/amelia-426/Catalyst/Alien City", // provide your build path "stack": "python_3_9", "env_variables": {}, "memory": 256, "scripts": {} }
Let’s quickly go through the working of the application:
GET Operation
- When you enter a city name in the application to check for a record of previous alien encounters, the onClick event for the Check button in index.html triggers the getAlienEncounter() function defined in main.js.
- This fires an Ajax call to the URL route defined in the function. The GET API defined in the app.py then invokes the getAlienCountFromCatalystDataStore() function and passes the request query.
- This function searches for the data in the AlienCity table in the Data Store by executing a ZCQL query.
- If a record matching the city name is found in the table, a positive signal is sent as the response. Otherwise, a negative signal is sent as the response.
- The application then displays a message that matches the response. A GIF matching the response defined in main.js is also displayed.
POST Operation
- When you enter a city name in the application to report an alien encounter, the onClick event for the Report button in index.html triggers the postAlienEncounter() function defined in main.js.
- This fires an Ajax call to the URL route defined in the function. The POST API defined in app.py then invokes the getAlienCountFromCatalystDataStore() function and passes a request query to check if a record with the same city name already exists.
- This function searches for the data in the AlienCity table in the Data Store by executing a ZCQL query. If the record already exists, a response is sent, which enables the client to display an appropriate message to the user.
- If there are no records for the city name, a new row is created in the AlienCity table for the city name entered by the user. A pop-up box is displayed in the client confirming the insertion of the record in the Data Store. An appropriate message is also pushed to the logs which can be checked from Logs, a Catalyst DevOps component under the Monitor section in the DevOps service section of the console.
Last Updated 2024-10-22 20:12:10 +0530 +0530