Crea una aplicación web completa - Parte 1

Crea una aplicación web completa - Parte 1

Entre lo mejor de saber programar es cuando notas un dolor/necesidad en la vida real y piensas en cómo se podría manejar este problema con la tecnología, con la programación. Cuando una nueva tendencia/manía comienza a suceder, no siempre ocurre de la mejor manera. A menudo, de hecho, el uso de esta nueva tendencia es bastante primitivo.

El poder del desarrollo

Con esta introducción me refiero a la nueva forma de acceder a los menús en los establecimientos de alimentación hoy en día: los menús online, generalmente disponibles mediante código qr en las mesas. Hace poco visité un restaurante y nada más entrar el camarero me preguntó: "¿Quieres el menú físico?" y esta vez, lamentablemente, le respondí que prefería probar el código qr uno, el modelo digital.

Como era de esperar, el enlace abrió un PDF compartido dentro de Google Drive. Creo que con esta información ya te puedes hacer una idea de la experiencia, ¿no? Necesita hacer zoom en la información, datos desactualizados y una experiencia visual muy mala, por decir lo menos. Sin mencionar que otros compañeros que estaban conmigo en la mesa tuvieron experiencias completamente diferentes: algunos ni siquiera podían abrirlo porque no tenían un lector de pdf en su dispositivo, por ejemplo. Y esta experiencia no solo se dio en este restaurante, sino también en varios otros que visité, se presenta el mismo problema.

Una solución de alto nivel

Aquí les presento la idea de una app que utilizaremos como caso de uso para construir una aplicación con backend, frontend, base de datos e infraestructura.

Una aplicación que genera un menú al que se puede acceder mediante un enlace generado a ese restaurante. El problema a resolver es proporcionar una manera fácil de crear un menú al que se pueda acceder fácilmente a través de un enlace/código QR. La usabilidad y capacidad de respuesta del contenido dentro del menú también es una de las características principales, entre ellas:

  • Gestión de categorías de productos.
  • CRUD de las categorías de entidad, es decir: la posibilidad de crear (create), leer (read), actualizar (update) y borrar (delete) la entidad.
  • Gestión de productos.
  • CRUD de la entidad de productos.
  • Gestión de la empresa (entidad).
  • Registro de la empresa en el sistema y posibilidad de cambiar sus propiedades.
  • Generar menú para enlace propio con código QR.
  • Página receptiva para usar en todos los dispositivos móviles.

La aplicación tendrá dos usuarios principales: la empresa (restaurante) y el cliente/consumidor. La única acción que realizará el consumidor será visualizar el menú, mientras que la empresa podrá gestionar todo su catálogo de productos.

El resultado final que buscamos es una aplicación web con su infraestructura provisionada en la nube y con un panel administrativo para la empresa que actualizará el menú disponible para el cliente.

Frontend x Backend

Estos dos componentes trabajan juntos para lograr un único objetivo: hacer que el usuario pueda usar la aplicación. De manera simplificada, una solicitud “viaja” desde el frontend al backend de la siguiente manera:

- El usuario escribe un dominio en su navegador y hace clic en Enter.
- El navegador realiza solicitudes al servidor (backend).
- El navegador recibe las respuestas del servidor (backend).
- La página está construida (frontend) para que el usuario pueda interactuar con ella. Estas interacciones hacen que este proceso se repita nuevamente.

Las definiciones son:

Backend: parte de la aplicación que no es visible para el usuario. Es él quien recibirá las solicitudes y procesará los datos para transmitirlos al cliente (que puede ser un navegador).

Frontend: parte de la aplicación que son visibles para el usuario. Por lo general, lo ejecuta el navegador y contiene código HTML, CSS y JS.

¿Cómo conectar los extremos?

Hablamos un poco sobre algunos componentes que harán que nuestra aplicación funcione: backend, frontend, base de datos, infraestructura en la nube. Me gustaría explicar un poco cómo se comunican estos primeros tres componentes.

Las solicitudes HTTP, presentes en la capa de aplicación del modelo OSI, son enviadas por el cliente al servidor que contiene encabezados HTTP y, si corresponde, también un cuerpo. Estas solicitudes se crean en el lado del cliente antes de enviarse y es probable que cada solicitud tenga una respuesta que devuelva los datos procesados ​​en ese proceso.

Quizás te preguntes cuáles datos se pasan a través de este proceso. En cuanto al backend, las respuestas varían entre:

  • Respuestas HTML.
  • Archivos estáticos: CSS, JS, imágenes.
  • Respuesta en JSON.
  • Sin cuerpo, solo encabezado y código de estado.

Y en frontend:

  • Solicitudes HTTP sin cuerpo.
  • Datos del formulario.
  • Solicitud JSON.

Flujo al usar un framework

Supongamos que para esta aplicación usaremos Django con plantillas de Django. Django es un framework web escrito en Python que se enfoca en el desarrollo rápido. En este caso, para el navegador que estará solicitando el contenido, es como si estuviera solicitando contenido estático. La solicitud llegará al servidor (físico/nube) y se pasa al servidor web (como nginx, por ejemplo). Desde esta capa se envía al framework (Django en este caso).

Aquí es donde ocurre la magia para generar contenido dinámico: es Django el que se encarga de ejecutar la lógica necesaria para devolver la “página estática” al navegador. Puede acceder a la base de datos o incluso a otros servicios para lograr este objetivo, en detalle: la URL solicitada se lee en el archivo urls.py y este archivo es el que vincula la URL con la vista (controlador) distinta para este proceso. La vista puede acceder a la base de datos a través del modelo o incluso de otra API. Al final, se generará una plantilla a la que se le pasarán datos de contexto. El HTML final se envía como respuesta al navegador y se procesa.

Pensando un poco en la experiencia del usuario

Por mucho que no seamos diseñadores, algo que siempre tenemos que hacer al diseñar una aplicación es pensar un poco en el viaje del usuario y las pantallas que vamos a crear. Toqué un poco este tema cuando hablé sobre la solución de alto nivel y seré un poco más específico cuando hable sobre las pantallas/funcionalidades que estarán presentes. Pantallas que se construirán:

  • Registro de la empresa.
  • Inicio de sesión de la empresa.
  • Página de inicio de la empresa.
  • Gestión de categorías: CRUD.
  • Gestión de productos: CRUD.
  • Gestión empresarial: cambio.
  • Página de menú.

La elección del stack frontend

En la sección “Flujo al usar un framework” hablé un poco sobre cómo los componentes internos de una biblioteca se comunican con un cliente (navegador). Para el ejemplo, usé Django y es el mismo que usaremos para desarrollar nuestra solución. Aquí hay algunas razones detrás de elegir este marco de Python:

  • Desarrollo rápido.
  • Modelo de usuario built-in.
  • Autenticación built-in.
  • Sistema de plantillas.
  • Comunidad activa.
  • Gran documentación.
  • Open source.
  • Escalable.
  • Seguro.

Estas son varias de las características que hacen de Django un excelente framework para el desarrollo web, pero podemos destacar el desarrollo rápido como una de las principales ventajas que me hizo elegir esta aplicación. Se puede decir que Django sigue la filosofía de batteries included, es decir, todo lo que puedas necesitar está disponible para su uso, sin necesidad de otra librería, construcción o desarrollo propios.

La otra característica principal que puedo destacar es mi nivel de comodidad/competencia con la herramienta. Como he estado trabajando los últimos dos años en Cornershop by Uber y la empresa usa Django para sus sistemas, termino desarrollando aplicaciones con el framework más rápido. Este factor es muy influyente para decidir qué stack utilizará una empresa para su producto, es decir, lo que su equipo actual ya domina se tendrá en cuenta para elegir qué stack/lenguaje elegir para avanzar.

¡Manos a la obra! A construir el frontend

Comencemos el desarrollo del código para la solución propuesta. Necesitará algunos requisitos previos instalados en su máquina:

- Última versión de Python.
- Django.

Después de tener estas aplicaciones instaladas, cree nuestra aplicación Django, ejecútala en tu terminal:

django-admin startproject menugenerator

Tendremos entonces el siguiente árbol de archivos:

Poco después, podemos crear nuestra primera aplicación en la carpeta raíz: store. Esta será la app responsable del restaurante/establecimiento registrado en nuestro sistema. Ejecuta:

django-admin startapp store

Tendremos entonces el siguiente árbol de archivos:

Ahora vamos a realizar algunos cambios en nuestra estructura actual aplicando buenas prácticas de diseño en Django. A todos los que quieran saber un poco más sobre este tema les recomiendo encarecidamente el libro Two Scoops of Django de los Greenfeld.

Usaremos una aplicación de dos niveles donde el primer nivel será el repository root (la primera carpeta a la izquierda de la imagen arriba del menugenerator de arriba). Y el segundo nivel lo formarán las carpetas de aplicaciones (store por ejemplo) además de la carpeta de configuración principal. El cambio de directorios se verá así:

De esta forma, cuando un desarrollador abra el proyecto, tendrá una vista de alto nivel de todo el proyecto. Recuerda cambiar las importaciones en config/settings.py de menugenerator a config. El archivo final se verá así:

Django settings for menugenerator project.

Generated by 'django-admin startproject' using Django 4.1.1.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'hidden'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
  'django.contrib.admin',
  'django.contrib.auth',
  'django.contrib.contenttypes',
  'django.contrib.sessions',
  'django.contrib.messages',
  'django.contrib.staticfiles',
]

MIDDLEWARE = [
  'django.middleware.security.SecurityMiddleware',
  'django.contrib.sessions.middleware.SessionMiddleware',
  'django.middleware.common.CommonMiddleware',
  'django.middleware.csrf.CsrfViewMiddleware',
  'django.contrib.auth.middleware.AuthenticationMiddleware',
  'django.contrib.messages.middleware.MessageMiddleware',
  'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'config.urls'

TEMPLATES = [
  {
      'BACKEND': 'django.template.backends.django.DjangoTemplates',
      'DIRS': [],
      'APP_DIRS': True,
      'OPTIONS': {
          'context_processors': [
              'django.template.context_processors.debug',
              'django.template.context_processors.request',
              'django.contrib.auth.context_processors.auth',
              'django.contrib.messages.context_processors.messages',
          ],
      },
  },
]

WSGI_APPLICATION = 'config.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases

DATABASES = {
  'default': {
      'ENGINE': 'django.db.backends.sqlite3',
      'NAME': BASE_DIR / 'db.sqlite3',
  }
}


# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
  {
      'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
  },
  {
      'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
  },
  {
      'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
  },
  {
      'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
  },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Ahora podemos ejecutar un comando que iniciará el servidor:

python manage.py runserver

La consola mostrará:

Al acceder al navegador en la url http://127.0.0.1:8000/ verás:

¡Excelente! Ahora tenemos nuestra aplicación ejecutándose en la web y con una aplicación creada.

¿Qué veremos a continuación?

En este artículo, expliqué la solución y cómo los componentes web se conectan con el framework, además de explicar cómo se comunican el frontend y el backend. En cuanto al desarrollo, solo hicimos que nuestra aplicación sirviera una plantilla HTML estática, pero aún necesitamos desarrollar todas las pantallas presentadas anteriormente y darles el dinamismo necesario.

Haremos esto mucho más paso a paso en los próximos artículos, donde verás:

- Creación de modelos.
- Descripción general del ORM de Django.
- Creación de plantillas.
- Descripción general del sistema de plantillas de Django.
- Acciones del usuario: autenticación de registro.
- Creación de las pantallas mencionadas al pensar un poco en la experiencia del usuario usando las plantillas.
- Aprovisionamiento de la aplicación en la infraestructura.


¡Y mucho más! Nos vemos en las próximas publicaciones :)

⚠️
Las opiniones y comentarios emitidos en este artículo son propiedad única de su autor y no necesariamente representan el punto de vista de Revelo.

Revelo Content Network da la bienvenida a todas las razas, etnias, nacionalidades, credos, géneros, orientaciones, puntos de vista e ideologías, siempre y cuando promuevan la diversidad, la equidad, la inclusión y el crecimiento profesional de los profesionales en tecnología.