Esta pagina se ve mejor con JavaScript habilitado

Django MVT, Apps y URLs

 ·  🎃 kr0m

En este artículo vamos a explicar tres conceptos relacionados con Django, el patrón de diseño modelo–vista–template (MVT), las Apps y las URLs, si conseguimos comprender estos términos de forma correcta la programación de la web resultará mucho mas sencilla ya que sabremos en todo momento que está ocurriendo y en que parte del código.

Antes de comenzar es recomendable leer los artículos anteriores sobre Django ya que son los pasos previos a este artículo:


El modelo MVT de Django funciona de la siguiente manera:

  • Los datos se almacenan en lo que Django llama modelos, estos son objetos con los atributos de un dato en concreto.
  • Las peticiones son atendidas por las vistas, estas procesan la petición y pasan los datos procesados al template a través de un contexto.
  • El template muestra la salida al cliente con los datos de la vista.

Las apps de Django son similares a módulos del proyecto, de este modo tendremos separado el código de cada conjunto de funcionalidades.

Las URLs son los paths de acceso a nuestas vistas, accediendo a una URL determinada se ejecutará la vista asociada a esta.

Por el momento tan solo tenemos el proyecto creado pero un proyecto sin apps no sirve de nada, creamos una app para la autenticación de usuarios y otra que será nuestra aplicación principal, separar las funcionalidades de esta forma nos permitirá en un futuro reutilizar código entre proyectos.

cd rxWod
source bin/activate
cd rxWodProject
python manage.py startapp rxWod
python manage.py startapp usersAuth

Como ya hemos explicado, las vistas atenderán las peticiones recibidas, para posteriormente enviarle los datos procesados al template, pero en este primer ejemplo vamos a prescindir del template a favor de una mayor simplicidad.

Creamos una vista en la app principal, esta responderá con el texto"Hello, world. You’re at rxWod: index view." :

vi rxWod/views.py

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at rxWod: index view.")

Creamos una vista en la app de autenticación de usuarios que responderá con el texto “Hello, world. You’re at usersAuth: register view.”:

vi usersAuth/views.py

from django.shortcuts import render
from django.http import HttpResponse

def register(request):
    return HttpResponse("Hello, world. You're at usersAuth: register view.")

El sistema de URLs de Django nos permitirá definir las urls de entrada a nuesta aplicación, mediante urls definiremos que peticiones deben ser atendidas por que vistas.
El proyecto principal tiene un fichero de urls, este hará referencia a otros mas específicos de cada aplicación, de este modo se consigue un control total.
Cada aplicación debe tener un NameSpace ya que cuando el proyecto empieza a tener mas apps es muy común que se repitan URLs en la configuración de cada app.

Creamos una URL en la que indicamos la vista a mostrar, en este caso index con NameSpace rxWod:

vi rxWod/urls.py

from django.urls import path
from . import views

app_name = 'rxWod'

urlpatterns = [
    path('', views.index, name='index'),
]

Creamos la URL ‘register/’ de la app usersAuth, el NameSpace es usersAuth:

vi usersAuth/urls.py

from django.urls import path
from . import views

app_name = 'usersAuth'

urlpatterns = [
    path('register/', views.register, name='register'),
]

Y finalmente las incluímos desde las URLs del proyecto, indicando el pattern del path y la URL en formato dotted(rxWod/urls -> rxWod.urls):

vi rxWodProject/urls.py

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('', include('rxWod.urls')),
    path('', include('usersAuth.urls')),
    path('admin/', admin.site.urls),
]

NOTA: La URL admin/ podéis ignorarla por ahora sin problema.

Volvemos a arrancar el servidor:

python manage.py runserver

Comprobamos la URL ‘index’:
http://127.0.0.1:8000/

Y la URL ‘register’:
http://127.0.0.1:8000/register

Configurar el idioma es muy importante ya que afecta a como se muestran las fechas, el timezone es igualmente importante ya que muestra la hora correcta directamente en las vistas.

vi rxWodProject/settings.py

LANGUAGE_CODE = 'es-es'
TIME_ZONE = 'Europe/Madrid'

El parámetro INSTALLED_APPS del fichero settings.py indica las aplicaciones instaladas, se podría decir que son las distintas funcionalidades de nuestro proyecto, algunas de ellas precisan de tablas en la base de datos, Django gestiona la creación de bases de datos y tablas según las necesidades del proyecto, pero para que pueda realizar dichas tareas debemos configurar las credenciales de acceso a la base de datos.

Generamos el fichero con las credenciales de acceso al PostgreSQL, al tener las credenciales externalizadas en un fichero de texto podremos indicarle a Git que ignore dicho fichero, de este modo el código podrá ser publicado sin desvelar nuestras credenciales de acceso a la base de datos:

vi rxWodProject/database_auth.txt

rxwod_user  
PASSWORD

Cambiamos la configuración a PostgreSQL:

vi rxWodProject/settings.py

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

database_auth_path = str(Path(__file__).resolve().parent) + '/database_auth.txt'
f = open(database_auth_path, "r")
lines = f.readlines()
f.close()
DB_USERNAME = lines[0].strip().split(' ')[0]
DB_PASSWORD = lines[1].strip().split(' ')[0]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'rxwod',
        'USER': DB_USERNAME,
        'PASSWORD': DB_PASSWORD,
    }
}

Le indicamos a Django que haga las migraciones(operaciones) necesarias en la base de datos, esto generará un fichero con los comandos a ejecutar sobre la base de datos para adaptar la estructura a los modelos definidos, en nuestro caso no se han modificado ningún modelo por lo tanto no generará ningún fichero nuevo:

python manage.py makemigrations

No changes detected

Pero cuando arrancamos el servidor web podemos leer que hay migraciones por aplicar, estas no son mas que las migraciones generadas por las apps como admin, auth … todas ellas apps internas de Django:

*You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.*  
*Run 'python manage.py migrate' to apply them.*

Aplicamos las migraciones:

python manage.py migrate

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Mas delante cuando creemos o modifiquemos nuestros modelos sí que aparecerán cambios al ejecutar el comando makemigrations.

Si te ha gustado el artículo puedes invitarme a un RedBull aquí