--- title: "Programar tu aplicación" url: https://docs.catalyst.zoho.com/es/tutorials/alien-city-appsail/python/code-app/ description: "Crea una aplicación y hospédala en Catalyst usando el servicio Catalyst AppSail y Catalyst Data Store que te permite reportar o buscar encuentros con alienígenas en una ciudad." last_updated: 2026-08-17T12:16:04Z service: All Services type: tutorial related_links: - name: "Catalyst SDK for AppSail" url: /es/cli/v1/initialize-resources/introduction/ --- # Programar tu aplicación Comencemos a programar la aplicación. Crea los siguientes archivos y directorios para almacenar tu código: * Un archivo de código Python en el directorio raíz de tu proyecto (`AlienCity/`), nómbralo "**app.py**". Este archivo contendrá la lógica del backend de tu aplicación. * Una carpeta en el directorio raíz de tu proyecto, nómbrala "**static**", y crea los siguientes archivos dentro de ella (`AlienCity/static/`): - **index.html**: Contiene el código HTML para el frontend de la aplicación - **main.js**: Contiene el código JavaScript de tu aplicación Esta es la estructura final de carpetas del proyecto *AlienCity*: ![catalyst_alien_city_cli_appsail_py_complete_dir](https://catalyst-docs-development.zohostratus.in/images/tutorials/alien-city-appsail-express/catalyst_alien_city_cli_appsail_py_complete_dir.webp) Programarás los archivos `app.py`, `index.html` y `main.js`. También actualizarás el archivo `app-config.json`. > **Nota:** Por favor, revisa el código en esta sección para asegurarte de que lo comprendes completamente. Copia el código a continuación y pégalo en los archivos correspondientes de tu proyecto usando un IDE y guarda los archivos. **app.py** ```python import sys sys.path.insert(0, './lib') from flask import Flask, request, jsonify import os import zcatalyst_sdk import logging tableName = 'AlienCity' # La tabla creada en el 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) # Consulta la tabla del Catalyst Data Store y verifica si existe una fila para la ciudad dada if len(rowid) == 0: # Si la fila no está presente, entonces se inserta una nueva fila logger.info("Alien alert!") # Se escribe en los logs. Puedes ver este log desde Logs en la sección Monitor de la consola datastore_service = capp.datastore() table_service = datastore_service.table(tableName) row_data = { columnName:name } table_service.insert_row(row_data) # Inserta el nombre de la ciudad como una fila en la tabla del Catalyst Data Store 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: # Si la fila está presente, entonces se envía un mensaje indicando duplicación 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) # Consulta la tabla del Catalyst Data Store y verifica si existe una fila para la ciudad dada 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): # Verifica si ya se reportó un encuentro con alienígenas para la ciudad dada consultando la tabla del Data Store 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.html** ```xml <!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.js** ```javascript function 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(); } ``` Actualiza el valor de la clave `command` como "**python3 app.py**" en el archivo `app-config.json`. Este es el [comando de inicio](https://docs.catalyst.zoho.com/es/serverless/help/appsail/key-concepts/appsail-execution/#startup-commands) que es específico para esta pila de programación y framework. **app-config.json** ```json { "command": "python3 app.py", "buildPath": "/Users/amelia-426/Catalyst/Alien City", // proporciona tu ruta de compilación "stack": "python_3_9", "env_variables": {}, "memory": 256, "scripts": {} } ``` Repasemos rápidamente el funcionamiento de la aplicación: 1. **Operación GET** * Cuando ingresas el nombre de una ciudad en la aplicación para verificar si hay un registro de encuentros previos con alienígenas, el evento onClick del botón **Check** en `index.html` activa la función `getAlienEncounter()` definida en `main.js`. * Esto realiza una llamada Ajax a la ruta URL definida en la función. La API `GET` definida en `app.py` luego invoca la función `getAlienCountFromCatalystDataStore()` y pasa la consulta de la solicitud. * Esta función busca los datos en la tabla *AlienCity* en el Data Store ejecutando una consulta ZCQL. * Si se encuentra un registro que coincide con el nombre de la ciudad en la tabla, se envía una señal *positiva* como respuesta. De lo contrario, se envía una señal *negativa* como respuesta. * La aplicación luego muestra un mensaje que coincide con la respuesta. También se muestra un GIF que coincide con la respuesta definida en `main.js`. 2. **Operación POST** * Cuando ingresas el nombre de una ciudad en la aplicación para reportar un encuentro con alienígenas, el evento onClick del botón **Report** en `index.html` activa la función `postAlienEncounter()` definida en `main.js`. * Esto realiza una llamada Ajax a la ruta URL definida en la función. La API `POST` definida en `app.py` luego invoca la función `getAlienCountFromCatalystDataStore()` y pasa una consulta de solicitud para verificar si ya existe un registro con el mismo nombre de ciudad. * Esta función busca los datos en la tabla *AlienCity* en el Data Store ejecutando una consulta ZCQL. Si el registro ya existe, se envía una respuesta que permite al client mostrar un mensaje apropiado al usuario. * Si no hay registros para el nombre de la ciudad, se crea una nueva fila en la tabla *AlienCity* para el nombre de la ciudad ingresado por el usuario. Se muestra un cuadro emergente en el client confirmando la inserción del registro en el Data Store. También se envía un mensaje apropiado a los logs que se puede verificar desde [Logs](https://docs.catalyst.zoho.com/es/devops/help/logs/introduction/), un componente de [Catalyst DevOps](https://docs.catalyst.zoho.com/es/devops/getting-started/introduction/) en la sección *Monitor* de la sección del servicio *DevOps* de la consola.