APLICAWEB 4to/Propuesta Intensiva 8 Semanas/Anexos/Banco de Preguntas · Unidad 2
20 preguntas · Unidad 2
✓

Banco de Preguntas Conceptuales — Unidad 2

Las 20 preguntas del “Examen conceptual rápido” de la Unidad 2 (Django, arquitectura MTV, MySQL en Aiven, ORM y migraciones, despliegue como Web Service en Render; Semanas 3-4). Cada una trae una respuesta modelo breve, las palabras clave mínimas que tu respuesta hablada debe incluir y, cuando aplica, el fragmento de tu propio código donde se ve ese concepto. Se complementan con los 20 retos de live coding de la Unidad 2.

Cómo se califica: el docente escucha tu respuesta en voz alta (sin leer) y marca “correcta” si cumples el mínimo indicado en el criterio de cada pregunta, explicando la relación entre los conceptos; no basta con nombrarlos sueltos. Las preguntas 1 a 5 son las oficiales de la lista de cotejo (2.4); las 6 a 20 son de refuerzo, tomadas de las guías de la Semana 3 y la Semana 4.
Unidad 2

Django + MySQL en la nube + Render

Pregunta 01

Recorre el flujo completo de una petición: desde que el navegador pide una URL hasta que Django devuelve el HTML final.

Respuesta modelo: El navegador pide /servicios/ → el urls.py del proyecto la delega con include al urls.py de core → esa ruta llama a la función servicios de views.py → la vista consulta el modelo (Servicio.objects.all()) y llama a render con una plantilla → Django rellena servicios.html y devuelve el HTML como respuesta HTTP.

urls.pyincludeviews.pyrendertemplaterespuesta HTTP
Mínimo para correcta: nombrar en orden al menos 4 pasos (URL → urls.py → vista → plantilla/respuesta) sin saltarse la vista.
En tu código — core/urls.py → core/views.py
# urls.py: la dirección 'servicios/' apunta a la función views.servicios
path('servicios/', views.servicios, name='servicios'),
# views.py: la función junta datos + plantilla y devuelve la respuesta
return render(request, 'core/servicios.html', {'servicios': lista_servicios})
Pregunta 02

¿Qué responsabilidad tiene el Model, cuál la View y cuál el Template? Da un ejemplo con tu propio Servicio.

Respuesta modelo: Model describe los datos y su tabla (class Servicio en models.py); View es la función que recibe la petición, pide datos al modelo y elige la plantilla (def servicios); Template es el HTML con {{ }} y {% %} que muestra esos datos (servicios.html).

Model = datos/tablaView = lógica/pegamentoTemplate = presentación HTMLejemplo propio
Mínimo para correcta: asignar bien las 3 responsabilidades y dar al menos un archivo real de su proyecto como ejemplo.
Pregunta 03

¿Qué ventaja tiene escribir Servicio.objects.all() en vez de un SELECT * FROM core_servicio a mano?

Respuesta modelo: El ORM traduce Python a SQL por ti: escribes Python, no dependes de la sintaxis de un motor concreto, obtienes objetos (no filas sueltas) con sus campos como atributos, y Django escapa los valores, lo que protege contra inyección SQL.

ORM traduce a SQLobjetos en vez de filasindependiente del motorinyección SQL
Mínimo para correcta: mencionar que el ORM genera el SQL + al menos 1 ventaja concreta (objetos, portabilidad o seguridad).
En tu código — core/views.py
# Python que escribes: Django lo convierte en SELECT ... FROM core_servicio
lista_servicios = Servicio.objects.all()
Pregunta 04

¿Por qué makemigrations y migrate son dos comandos separados y no uno solo?

Respuesta modelo: makemigrations solo compara tus modelos con las migraciones existentes y escribe un archivo con el plan de cambios (ej. 0001_initial.py); no toca la base. migrate ejecuta ese plan contra MySQL. Separarlos permite revisar el plan, versionarlo en Git y aplicarlo igual en otro entorno (Render).

plan de cambiosno toca la BDaplica en MySQLse versiona en Git
Mínimo para correcta: distinguir “genera el plan/archivo” de “lo aplica en la base de datos”.
En tu código — terminal
# genera core/migrations/0001_initial.py (solo el plan)
$ python manage.py makemigrations core
# ejecuta el plan: crea la tabla core_servicio en MySQL
$ python manage.py migrate
Pregunta 05

¿Qué pasaría si subieras tu archivo .env real a un repositorio público de GitHub?

Respuesta modelo: Cualquiera podría leer el host, usuario y contraseña de tu MySQL en Aiven (y tu SECRET_KEY) y entrar a tu base de datos: ver, cambiar o borrar datos. Borrarlo después no alcanza porque queda en el historial de Git; hay que cambiar las credenciales. Por eso .env va en .gitignore y se sube solo .env.example.

credenciales expuestasacceso a la BDqueda en el historial.gitignore.env.example
Mínimo para correcta: decir que se exponen las credenciales + cómo se evita (.gitignore / .env.example) o qué hacer (rotar la contraseña).
En tu código — .gitignore
# .env: el archivo con tus contraseñas reales, nunca debe llegar a GitHub
.env
Pregunta 06

¿Qué es el entorno virtual (venv) y qué relación tiene con requirements.txt?

Respuesta modelo: El venv es una copia aislada de Python solo para este proyecto: lo que instalas con pip no se mezcla con otros proyectos. No se sube a GitHub; en su lugar se sube requirements.txt (hecho con pip freeze), la lista con la que cualquiera —incluido Render— recrea el mismo entorno con pip install -r requirements.txt.

aislado por proyectono se sube (venv/)pip freezepip install -r
Mínimo para correcta: explicar “aislado” + que requirements.txt permite recrear el entorno en otra máquina/Render.
Pregunta 07

¿Para qué instalaste pymysql y qué hace pymysql.install_as_MySQLdb()?

Respuesta modelo: Django necesita un driver para hablar con MySQL. PyMySQL es un conector escrito en Python puro; install_as_MySQLdb() hace que Django lo use como si fuera el driver oficial (MySQLdb), que es el que espera el backend django.db.backends.mysql.

driver/conectorPython purose hace pasar por MySQLdbENGINE mysql
Mínimo para correcta: decir que es el conector entre Django y MySQL + qué hace la línea install_as_MySQLdb.
En tu código — miproyecto_pdb/settings.py
# pymysql: el conector que instalaste con pip
import pymysql
# Django lo usa como si fuera el driver oficial MySQLdb
pymysql.install_as_MySQLdb()
Pregunta 08

¿Qué diferencia hay entre .env y .env.example, y cuál entregas?

Respuesta modelo: .env tiene los valores reales (contraseña de Aiven, etc.), vive solo en tu computadora y está en .gitignore. .env.example tiene las mismas claves con valores de relleno, se sube al repo y documenta qué variables necesita el proyecto. Se entrega .env.example.

valores realesvalores de ejemplomismas clavesse entrega .env.example
Mínimo para correcta: distinguir valores reales/no se sube vs. ejemplo/sí se sube.
Pregunta 09

¿Qué hace config('DB_PORT', default='3306') y para qué sirven default y cast?

Respuesta modelo: config busca la variable primero en las variables de entorno del sistema (lo que usa Render) y si no, en el .env. default es el valor que se usa si la variable no existe. cast convierte el texto leído a otro tipo, por ejemplo cast=bool para DEBUG o cast=Csv() para ALLOWED_HOSTS.

lee .env / entornodefault si no existecast convierte el tipomismo código local y Render
Mínimo para correcta: explicar qué lee config + el rol de default (o de cast).
En tu código — miproyecto_pdb/settings.py
# PORT: lee DB_PORT; si no está definida, usa '3306'
'PORT': config('DB_PORT', default='3306'),
Pregunta 10

¿Por qué el bloque DATABASES tiene 'OPTIONS': {'ssl': {'ssl-mode': 'REQUIRED'}}?

Respuesta modelo: Porque la base está en la nube y la conexión viaja por internet: Aiven exige que vaya cifrada (SSL/TLS) para que nadie pueda leer el usuario, la contraseña ni los datos en el camino. Sin esa opción, la conexión es rechazada.

cifrado SSL/TLSviaja por internetAiven lo exigeprotege credenciales
Mínimo para correcta: relacionar SSL con conexión cifrada + que es un requisito de Aiven por ser remota.
Pregunta 11

¿Qué es una “app” de Django y por qué la plantilla va en core/templates/core/ (con “core” repetido)?

Respuesta modelo: Una app es una unidad de funcionalidad dentro del proyecto (la creaste con startapp core y la registraste en INSTALLED_APPS). La carpeta repetida es una convención: Django junta las plantillas de todas las apps, y el subdirectorio con el nombre de la app evita que dos apps con un servicios.html se confundan; por eso se pide 'core/servicios.html'.

unidad de funcionalidadINSTALLED_APPSevita choques de nombres'core/servicios.html'
Mínimo para correcta: definir app + explicar que el “core” repetido evita confusiones entre apps.
Pregunta 12

¿Qué diferencia hay entre {{ servicio.titulo }} y {% for servicio in servicios %} en una plantilla?

Respuesta modelo: {{ }} muestra un valor (una variable del contexto o un atributo). {% %} es una etiqueta que ejecuta lógica de plantilla (bucles, condiciones, url) y no imprime nada por sí misma. El for necesita cerrar con {% endfor %}.

{{ }} muestra{% %} lógica/etiquetaendfor obligatoriocontexto
Mínimo para correcta: distinguir “mostrar un valor” de “ejecutar lógica”.
En tu código — servicios.html
<!-- {% for %}: repite la fila por cada servicio -->
{% for servicio in servicios %}
<!-- {{ }}: imprime el título del servicio actual -->
<td>{{ servicio.titulo }}</td>
<!-- cierra el bucle -->
{% endfor %}
Pregunta 13

¿Para qué sirve include('core.urls') en el urls.py del proyecto y para qué el name= de cada ruta?

Respuesta modelo: include delega un grupo de direcciones a otra app: el proyecto dice “todo lo que llegue a la raíz lo resuelve core/urls.py”. name= es un alias interno para referirse a la ruta sin escribir la dirección, por ejemplo con {% url 'servicios' %}; si la dirección cambia, los enlaces siguen funcionando.

include delegaurls del proyecto vs. de la appname = alias{% url %}
Mínimo para correcta: explicar la delegación de include + el uso del name como alias.
Pregunta 14

¿Por qué propietario es un ForeignKey a User y qué hace on_delete=models.CASCADE?

Respuesta modelo: Porque cada servicio pertenece a un usuario: la ForeignKey crea en MySQL la columna propietario_id, que apunta a una fila de la tabla de usuarios (relación muchos-a-uno: un usuario, muchos servicios). CASCADE indica que si se borra ese usuario, se borran también sus servicios.

relación muchos a unopropietario_idtabla auth_userCASCADE borra en cadena
Mínimo para correcta: explicar la relación servicio→usuario + qué pasa con CASCADE al borrar al usuario.
En tu código — core/models.py
# ForeignKey: genera la columna propietario_id, que apunta a un User
propietario = models.ForeignKey(User, on_delete=models.CASCADE)
Pregunta 15

¿Qué pasa en /admin si tu modelo no tiene el método __str__?

Respuesta modelo: Cada registro aparecería como “Servicio object (1)”, “Servicio object (2)”… porque Django no sabría qué texto usar para representarlo. __str__ define ese texto; en tu modelo devuelve self.titulo. No requiere migración porque no cambia la tabla.

Servicio object (1)texto que representa al objetoself.titulosin migración
Mínimo para correcta: decir qué se vería sin __str__ + qué devuelve el suyo.
Pregunta 16

¿Por qué en Render se usa gunicorn y no python manage.py runserver?

Respuesta modelo: runserver es un servidor de desarrollo: pensado para una sola persona en su computadora, sin la seguridad ni el rendimiento necesarios. gunicorn es un servidor WSGI de producción que atiende varias peticiones a la vez; en Render se arranca con el Start Command gunicorn miproyecto.wsgi (el nombre de tu proyecto).

runserver = desarrollogunicorn = producciónWSGI / wsgi.pyStart Command
Mínimo para correcta: contrastar desarrollo vs. producción + mencionar el Start Command o wsgi.
Pregunta 17

¿Qué problema resuelve WhiteNoise y qué hace collectstatic con STATIC_ROOT?

Respuesta modelo: Con DEBUG=False Django deja de servir los archivos estáticos (CSS/JS/imágenes, como los del admin). WhiteNoise permite que la propia app los sirva sin un servidor aparte. collectstatic (en el Build Command) copia todos los estáticos de las apps a la carpeta STATIC_ROOT (staticfiles/), de donde WhiteNoise los entrega comprimidos. Su middleware va justo después de SecurityMiddleware.

estáticos con DEBUG=Falsesin servidor apartecollectstatic → STATIC_ROOTdespués de SecurityMiddleware
Mínimo para correcta: explicar que sirve estáticos en producción + qué hace collectstatic.
En tu código — miproyecto_pdb/settings.py
# STATIC_ROOT: carpeta donde collectstatic junta todos los estáticos
STATIC_ROOT = BASE_DIR / 'staticfiles'
Pregunta 18

¿Por qué en Render DEBUG debe ser False y qué controla ALLOWED_HOSTS?

Respuesta modelo: Con DEBUG=True, ante un error Django muestra código, rutas y configuración a cualquier visitante. En producción va en False y se ve un error genérico. ALLOWED_HOSTS es la lista de dominios que Django acepta atender; con DEBUG=False, si el dominio de Render no está ahí, responde Bad Request (400).

DEBUG expone detalleserror genéricolista de dominiosBad Request (400)
Mínimo para correcta: explicar el riesgo de DEBUG=True + qué pasa si el dominio no está en ALLOWED_HOSTS.
Pregunta 19

¿Por qué en la Unidad 1 fue un Static Site y en la Unidad 2 un Web Service en Render? ¿Qué hacen el Build y el Start Command?

Respuesta modelo: El portafolio era HTML/CSS fijo: bastaba con servir archivos. Django necesita un proceso de Python corriendo todo el tiempo que atienda cada petición y hable con MySQL: eso es un Web Service. El Build Command prepara (pip install -r requirements.txt + collectstatic + migrate) y el Start Command arranca el servidor (gunicorn ...wsgi).

archivos fijos vs. servidor Pythonproceso corriendoBuild = instalar/prepararStart = gunicorn
Mínimo para correcta: contrastar sitio estático con servidor Python + decir qué hace al menos uno de los dos comandos.
Pregunta 20

Tu computadora y Render usan la misma MySQL de Aiven, y migrate está en el Build Command de Render. Si ya migraste en local, ¿qué pasa en el siguiente deploy y por qué no se usa la Shell?

Respuesta modelo: En el plan Free de Render no existe la pestaña Shell, por eso migrate va al final del Build Command y corre solo en cada deploy. Al correr, Django revisa la tabla django_migrations de la base de Aiven, ve que todas las migraciones ya están aplicadas (las aplicaste desde tu compu contra esa misma base) y el log dice “No migrations to apply”. Si el push trae una migración nueva que nadie aplicó, ese mismo paso la aplica (Applying ... OK). Por eso los datos cargados en /admin de Render también se ven en local.

sin Shell en plan Freemigrate en el Build Commandmisma base Aivendjango_migrationsNo migrations to apply
Mínimo para correcta: decir que migrate corre en el Build Command (no en una Shell) + que la base es la misma y Django sabe qué aplicó (django_migrations / “No migrations to apply”).
En tu práctica — Render → Settings → Build Command
# instala paquetes, junta estáticos y aplica migraciones en Aiven, en cada deploy
pip install -r requirements.txt && python manage.py collectstatic --noinput && python manage.py migrate
↑ Números