Este guión de prácticas ha sido elaborado siguiendo la filosofía de los tutoriales de página de Django. Este guión ha sido adaptado para las clases de SAT y SARO de los Grados que se imparten en la Escuela de Ingeniería de Telecomunicación de la Universidad Rey Juan Carlos.
Para este guión, partimos del estado del guión #3, que se puede encontrar en el siguiente repositorio: https://gitlab.etsit.urjc.es/cursosweb/x-serv-15.6-cms_put-resolved del GitLab de la ETSIT. Nota: si partes del repositorio, nota que el superusuario será "grex" y la contraseña "pakito"; esto es así, porque los usuarios se guardan en la base de datos (que viene incluida en el repo).
Hasta ahora, nuestra aplicación no tenía en cuenta quién hacía qué, cualquiera podía subir contenidos y comentarios, así como cambiarlos. Vamos a ver cómo introducir autenticación y autorización en nuestra aplicación de Django. Para ello, vamos a añadir una primera vista a nuestra aplicación, tal que así:
from django.http import HttpResponse
[...]
def loggedIn(request):
if request.user.is_authenticated:
logged = "Logged in as " + request.user.username
else:
logged = "Not logged in. <a href='/admin/'>Login via admin</a>"
return HttpResponse(logged)
En esta vista, podemos ver que existe un objeto request.user
que tiene una propiedad is_authenticated
. request.user
viene determinado a partir de la sesión; si hay una sesión abierta, habrá un usuario (que estará autenticado). Si no hay sesión, entonces no habrá un usuario autenticado.
Para que la vista funcione, hemos de añadir a cms/urls.py
la siguiente regla:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('<str:llave>', views.get_content),
path('loggedIn', views.loggedIn),
]
Si ejecutamos el servidor y pedimos loggedIn nos dará un error 404. Esto es porque las URLs se comprueban siguiendo el orden de definición de urls.py. Con la configuración actual, si pedimos loggedIn se cumple al regla '<str:llave>' al ser loggedIn una cadena de caracteres y se ejecutará su vista. Para que todo funcione bien, Nota que en caso de no estar autenticado, la página de respuesta contiene un enlace. Si pinchas sobre ese enlace, te llevará a la página de inicio del portal de gestión de tu proyecto Django, lo que generalmente llamamos admin (o la interfaz de administración). Si recuerdas bien, creamos hace un par de prácticas un superusuario. Introduce sus credenciales para entrar en la interfaz de administración. Y a continuación, vuelve a visitar la página loggedIn. Podrás comprobar que estás autenticado y que te saluda con Ya que hemos visto como hacer login, véamos como salirnos de nuestra sesión (logout). Para ello, añadamos la siguiente vista: Como se puede observar, la vista es muy sencilla. Básicamente hace uso del método Además, hacemos uso de un shortcut, que es Debemos modificar Prueba a visitar la página de Hecho el logout, veamos cómo hacer login. Hacer login no es tan sencillo como logout, porque hace falta tener un formulario de autenticación (como el que hemos usado, prestado, de admin). Django ofrece funcionalidad para realizar el login, pero necesita que nosotros específiquemos cómo va a ser ese formulario de autenticación. Así que vamos a implementar la funcionalidad de login y lo haremos para el proyecto entero (i.e., para todas las apps). Para eso, primero debemos modificar el urls.py del proyecto: En este código, la parte relevante viene dada por la línea donde importamos la vista Para generar la plantilla que nos permita tener el formulario de login, primero debemos indicar en settings.py el diretorio donde estará nuestra plantilla. Recordarás que algo similar hicimos para las plantillas de nuestra aplicación, aunque entonces no necesitamos indicar nada en settings.py ya que las plantillas para las aplicaciones siempre se encuentran en el subdirectorio Una vez modificado el fichero settings.py, tendremos que crear el subdirectorio Como puedes observar, se trata de un formulario HTML, que cuando se pulsa el botón de 'login', envía un POST a Prueba la página web de login y el formulario. Verás que una vez logueado con éxito, te redirigirá a una página que dará un 404. Esta redirección se puede cambiar. Busca en la documentación de Django en la web, cómo hacerlo. Si has llegado hasta aquí, pon en el chat de Teams el siguiente mensaje: "Acabo de terminar la parte de login". Los sitios web generalmente necesitan servir ficheros adicionales, como imágenes, código JavaScript u hojas de estilo CSS. En Django, al ser ficheros que no se modifican, los llamaremos «static files» y en vez de servirse como una vista (que es para generar paǵinas o servicios dinaḿicos), lo haremos de otra manera. Para eso, Django ofrece
Asegúrate que En tu archivo de settings, define En tus plantillas, puedes usar la etiqueta Almacena, por tanto, tus ficheros estáticos en una carpeta llamada Probemos a añadir una imagen. Para ello, vamos a crear una vista que utilice la plantilla que hay en Nota que no pasamos ningún valor como contexto a la plantilla (la única variable es static que viene de settings.py), por lo que el contexto es un diccionario vacío. Ahora, busca una imagen en formato JPEG y guárdala como Si todo ha ido bien, deberías ver la imagen en el navegador. Aviso: Sirviendo ficheros estáticos Una vez configurado, podrás servir los ficheros estáticos. Ten en cuenta, sin embargo, que durante el desarrollo, si utilizas Más adelante, en esta misma práctica, en Desplegando ficheros estáticos, podrás encontrar estrategias válidas para servir ficheros estáticos en producción. Tu proyecto probablemente tenga también elementos que no estén ligados a una aplicación específica. Además de usar un directorio De esta manera, Django tendrá ficheros estáticos en dos localizaciones: en el subdirectorio Si utilizas Por ejemplo, si tu Para acceder vía tu navegador, tendrás que apuntar a http://localhost:8000/static/imagen.jpg (siendo imagen.jpg el nombre de la imagen que has almacenado en el subdirectorio Nota Esta función auxiliar fucionará en modo debug sólo si el prefijo es local (esto es, Además, esta función auxiliar sólo sirve del directorio Si has llegado hasta aquí, pon en el chat de Teams el siguiente mensaje: "Acabo de terminar la práctica de hoy". A continuación, podrás ver cuestiones a tener en cuenta: Primero, dónde poner archivos que suban los usuarios, y el segundo, cómo se hace cuando se despliega en producción. Durante el desarrollo, puedes servir ficheros estáticos subidos por usuarios a
Por ejemplo, si tu Indica como Ejecuta la instrucción Esto copiará todos tus ficheros estáticos en el directorio
Usa un servidor web de tu elección para servir los ficheros estáticos. El documento Deploying static files ofrece algunas estrategias comunes para desplegar ficheros estáticos.cms/urls.py
debería ser así:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('loggedIn', views.loggedIn),
path('<str:llave>', views.get_content),
]
request.user
, que es tu nombre de usuario.from django.contrib.auth import logout
from django.shortcuts import redirect
[...]
def logout_view(request):
logout(request)
return redirect("/cms/")
logout
que se importa de django.contrib.auth
. django.contrib.auth
es una de las aplicaciones que vienen por defecto en Django.redirect
. redirect
nos permite hacer una redirect como respuesta HTTP.cms/urls.py
para que quede así:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('loggedIn', views.loggedIn),
path('logout', views.logout_view),
path('<str:llave>', views.get_content),
]
logout
y posteriormente la de loggedIn
. Comprobarás que ciertamente has salido de la sesión.from django.contrib import admin
from django.urls import include, path
from django.contrib.auth.views import LoginView as login
urlpatterns = [
path('cms/', include('cms.urls')),
path('calc/', include('calc.urls')),
path('admin/', admin.site.urls),
path('login', login.as_view()),
]
login
de django.contrib.auth.views
. Lo que estamos haciendo, por tanto, es utilizar una vista de una aplicación Django (llamada auth) y que viene preisntalada en Django. Esta vista realiza todas las acciones necesarias para gestionar el login, pero hace uso de una plantilla.templates
de la aplicación. Para plantillas de proyecto, necesitamos sin embargo indicar dónde van a estar alojadas:TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates', ],
'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',
],
},
},
]
templates
. Este subdirectorio lo crearemos en el raíz de Django (donde está manage.py). Dentro del subdirectorio templates
, a su vez crearemos otro subdirectorio llamado registration
y ahí crearemos un fichero llamado login.html
. La razoń de todo esto es que la vista login
buscará la plantilla en registration/login.html
dentro del directorio donde se guarden todas las plantillas (en nuestro caso, templates
). El contenido de la plantilla es el que se muestra a continuación:<html>
<body>
<form method="POST" action="/login">
{% csrf_token %}
<table>
<tr>
<td>Username</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>Password</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="login" />
</form>
</body>
</html>
login
. El formulario tiene dos campos, form.username
y form.password
, que es donde se han de introducir las credenciales. Una cuestión interesante es la línea justo después de la etiqueta form. Esta línea incluye el csrf_token
, que es un código que se despliega como un campo del formulario oculto. De esta manera, Django puede controlar que todo POST que le llegue haya sido mediante el envío de un formulario propio; en caso de que reciba un POST sin el CSRF correcto, entenderá que puede ser debido a un ataque y lo desechará.Gestionando ficheros estáticos¶
django.contrib.staticfiles
para gestionarlos. A continuación veremos cómo hacerlo.Configurando static files¶
django.contrib.staticfiles
está incluido en
INSTALLED_APPS
de settings.py.STATIC_URL
, por ejemplo:STATIC_URL = '/static/'
static
para construir la URL de tus elementos estáticos. Así, sólo has de indicar el camino relativo a donde se pida el archivo. Por ejemplo, en la plantilla a continuación se indica que la imagen example.jpg se encuentra dentro del subdirectorio de ficheros estáticos de tu aplicación, cms.{% load static %}
<img src="{% static "cms/example.jpg" %}" alt="My image">
static
en tu aplicación. Por ejemplo cms/static/cms/example.jpg
.cms/templates/cms/plantilla.html
:from django.http import HttpResponse
[...]
from django.template import loader
[...]
def imagen(request):
template = loader.get_template('cms/plantilla.html')
context = {}
return HttpResponse(template.render(context, request))
cms/static/cms/example.jpg
. Para que se vea la imagen, vamos a tener que modificar cms/urls.py
para que quede así:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index),
path('imagen', views.imagen),
path('loggedIn', views.loggedIn),
path('logout', views.logout_view),
path('<str:llave>', views.get_content),
]
django.contrib.staticfiles
, los ficheros estáticos serán servidos de manera automática por runserver
cuando DEBUG
esté puesto a True
(mira django.contrib.staticfiles.views.serve()
). Este método es ineficiente y probablemente inseguro,
así que no debería utilizarse en entornos en producción.static/
dentro de tus apps,
puedes definir una lista de directorios (STATICFILES_DIRS
) en tu fichero settings donde Django buscará ficheros estáticos. Nota que STATICFILES_DIRS
es una variable que no existe por defecto en settings.py, por lo que tendrás que crearla. Por ejemplo:STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
'/var/www/static/',
]
static
del proyecto y en '/var/www/static/'
(tienen que ser directorios donde tengas permiso de lectura). Crea el subdirectorio static
e incluye en el mismo una imagen.Sirviendo ficheros estáticos durante el desarrollo¶
django.contrib.staticfiles
tal y como se explica más arriba,
runserver
lo hará de manera automática cuando DEBUG
sea
to True
. Si no tienes django.contrib.staticfiles
en
INSTALLED_APPS
, puedes servir ficheros estáticos de todas maneras utilizando la vista
django.views.static.serve()
.STATIC_URL
se ha definido como /static/
, puedes hacerlo añadiendo el siguiente código a tu urls.py:from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... aquí vienen el resto del URLConfs ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
/static/
)./static/
) y no una URL (por ejemplo,
http://static.example.com/
).STATIC_ROOT
; no hace descubrimiento de ficheros estáticos como sí hace
django.contrib.staticfiles
.Sirviendo ficheros estáticos de un usuario durante el desarrollo¶
MEDIA_ROOT
usando la vista django.views.static.serve()
.MEDIA_URL
está definida como /media/
en settings.py, puedes servir estos ficheros añadiendo el siguiente código a tu urls.py:from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Despliegue¶
django.contrib.staticfiles
ofrece una manera de agrupar todos los ficheros estáticos en un único directorio y servirlos de manera sencilla.
STATIC_ROOT
en settings.py el directorio desde el cual te gustaría servir todos los ficheros estáticos, por ejemplo:STATIC_ROOT = "/var/www/example.com/static/"
collectstatic
de Django:$ python manage.py collectstatic
STATIC_ROOT
.