Escuela T ´ecnica Superior de Ingenier´ıa Inform ´atica
Grado en ingenier´ıa del software
Aplicaci ´on web para la gesti ´on de rutas tur´ısticas
Web application for tourist routes management
Realizado por
ROC´IO ARREBOLA PASCUAL
Dirigido por
JOS ´
E MAR´IA ´
ALVAREZ PALOMO
Departamento
LENGUAJES Y CIENCIAS DE LA COMPUTACI ´
ON
UNIVERSIDAD DE M ´ALAGA M ´alaga, junio de 2017.
Resumen:
En este proyecto se aborda la creaci ´on de una aplicaci ´on web utilizando Django y los servicios web de Amazon (Amazon Web Services). En esta aplicaci ´on se pretende re-unir a los viajeros de todo el mundo para que compartan sus experiencias con el resto de usuarios.
La aplicaci ´on se alojar ´a en instancias de Amazon EC2, el servidor ofertado por Ama-zon. Estas instancias se administrar ´an en AWS Elastic Beanstalk por medio de AWS Auto Scaling, que aumentar ´a o reducir ´a la capacidad de Amazon EC2 en funci ´on al tr ´afico de carga. Para la base de datos se utilizar ´a una instancia de Amazon RDS, el servidor de bases de datos relacionales de Amazon, con una base de datos MySQL. Tambi ´en se har ´a un estudio del gasto que supone tener una aplicaci ´on alojada en AWS mediante el tablero de facturaci ´on que proporciona Amazon.
Para comprobar que AWS Auto Scaling hace un balanceo de carga correcto, se utili-zar ´an herramientas para simular un gran n ´umero de peticiones al servidor de la apli-caci ´on, de modo que haya que aumentar la capacidad de Amazon EC2.
Palabras clave: Amazon Web Services, Django, aplicaci ´on web, Amazon EC2, AWS Elastic Beanstalk, AWS Auto Scaling, Amazon RDS.
Abstract:
This project deals with the creation of a web application using Django and Amazon Web Services. The primary goal of this application is gathering travellers around the world so that they can share their experiences with the rest of users.
This application will be hosted in Amazon EC2 instances, AWS’s server. Instances will be managed in AWS Elastic Beanstalk by AWS Auto Scaling, that will increase or re-duce server’s capacity according to application’s traffic. For the database, an Amazon RDS instance will be used, which is the Amazon’s relational database server, into this instance a MySQL database will be used. Furthermore, in order to study the costs of hosting a web application in AWS, Amazon’s billing dashboard will be used.
For the shake of checking that AWS Auto Scaling is scaling in a proper way, tools to simulate a big number of requests to the application’s server will be used, so that it will be necessary to increase Amazon EC2’s capacity.
´Indice general
1. Introducci ´on 1
1.1. Motivaci ´on . . . 1
1.2. Objetivos . . . 1
1.3. Django . . . 2
1.3.1. ¿Qu ´e es Django? . . . 2
1.3.2. Modelos . . . 4
1.4. Amazon Web Services (AWS). . . 5
1.5. Bootstrap . . . 6
2. Requisitos 7 2.1. Descripci ´on de participantes y usuarios . . . 7
2.1.1. Perfiles de usuario . . . 7
2.2. Requisitos funcionales . . . 8
2.3. Requisitos no funcionales . . . 10
2.4. Requisitos de documentaci ´on . . . 11
3. Dise ˜no 13 3.1. Diagrama de clases . . . 13
4. Visi ´on de conjunto 17 5. Primera iteraci ´on 19 5.1. Requisitos implementados . . . 19
5.2. Desarrollo . . . 20
5.2.1. Modelos . . . 20
5.2.2. Vistas . . . 21
5.2.3. Formularios . . . 24
5.2.4. Templates . . . 24
6.1. Requisitos implementados . . . 27
6.2. Desarrollo . . . 28
6.2.1. Vistas . . . 28
6.2.2. Templates . . . 29
6.3. Pruebas . . . 30
7. Tercera iteraci ´on 31 7.1. Requisitos implementados . . . 31
7.2. Desarrollo . . . 32
7.2.1. Formularios . . . 32
7.2.2. Vistas . . . 33
7.2.3. Templates . . . 35
8. Cuarta iteraci ´on 37 8.1. Requisitos implementados . . . 37
8.2. Desarrollo . . . 38
8.2.1. Modelos . . . 38
8.2.2. Vistas . . . 38
8.2.3. Formularios . . . 39
8.2.4. Templates . . . 40
9. Quinta iteraci ´on 41 9.1. Requisitos implementados . . . 41
9.2. Desarrollo . . . 41
9.2.1. Vistas . . . 41
9.2.2. Templates . . . 43
10. Sexta iteraci ´on 49 10.1.Modificaciones . . . 49
10.2.Desarrollo . . . 49
10.2.1. Modelos . . . 49
10.2.2. Vistas . . . 50
10.2.3.Templates . . . 50
11. Conclusiones 53 11.1.Opini ´on sobre la uni ´on deDjango yAmazon Web Services . . . 53
11.2.An ´alisis de resultados . . . 54
12. Bibliograf´ıa 57 Bibliograf´ıa . . . 57
B. Casos de prueba 83
C. Manual de usuario 135
C.1. Introducci ´on . . . 135
C.2. Instalaci ´on . . . 135
C.2.1. Requisitos del sistema . . . 135
C.2.2. Instalaci ´on . . . 136
C.3. Funcionalidades . . . 136
C.3.1. Crear cuenta . . . 136
C.3.2. Recuperar la contrase ˜na . . . 137
C.3.3. Iniciar sesi ´on . . . 138
C.3.4. Cerrar sesi ´on . . . 139
C.3.5. Crear una ruta . . . 139
C.3.6. Editar una ruta . . . 139
C.3.7. Borrar una ruta . . . 140
C.3.8. Crear un d´ıa . . . 141
C.3.9. Editar un d´ıa . . . 143
C.3.10.A ˜nadir un lugar de inter ´es a un d´ıa . . . 144
C.3.11.Quitar un lugar de inter ´es de un d´ıa . . . 146
C.3.12.Borrar un d´ıa . . . 146
C.3.13.Crear un lugar de inter ´es . . . 147
C.3.14.Editar un lugar de inter ´es . . . 148
C.3.15.B ´usqueda . . . 149
C.3.16.Seguir una ruta . . . 149
C.3.17.Dejar de seguir una ruta . . . 150
C.3.18.Seguir a un usuario . . . 150
C.3.19.Dejar de seguir un usuario . . . 151
C.3.20.Valorar una ruta . . . 151
C.3.21.Borrar la valoraci ´on de una ruta . . . 152
C.3.22.Valorar un lugar de inter ´es . . . 152
C.3.23.Borrar la valoraci ´on de un lugar de inter ´es . . . 153
C.3.24.Editar perfil de usuario . . . 154
´Indice de figuras
1.1. Mapa de las regiones geogr ´aficas usadas por AWS . . . 5
3.1. Diagrama de clases inicial . . . 14
3.2. Diagrama de clases final . . . 15
C.1. Registro de usuario. Paso 1. P ´agina de inicio. . . 136
C.2. Registro de usuario. Paso 2. P ´agina de registro. . . 137
C.3. Recuperar la contrase ˜na. Paso 1. P ´agina de inicio. . . 137
C.4. Recuperar la contrase ˜na. Paso 2. P ´agina de recuperaci ´on de la contra-se ˜na. . . 138
C.5. Iniciar sesi ´on. Paso 1. P ´agina principal. . . 138
C.6. Cerrar sesi ´on. . . 139
C.7. Crear ruta. Paso 1.a. Pantalla principal . . . 140
C.8. Crear ruta. Paso 1.b. Pantalla principal . . . 140
C.9. Crear ruta. Paso 2. Formulario de creaci ´on de la ruta. . . 141
C.10.Editar ruta. Paso 1. P ´agina de ruta . . . 141
C.11.Editar ruta. Paso 2. P ´agina de edici ´on de ruta . . . 142
C.12.Borrar ruta. Paso 1. P ´agina de ruta . . . 142
C.13.Borrar ruta. Paso 2. Confirmaci ´on de la acci ´on . . . 142
C.14.Crear d´ıa. Paso 1. P ´agina de ruta . . . 143
C.15.Crear d´ıa. Paso 2. P ´agina de creaci ´on del d´ıa . . . 143
C.16.Editar d´ıa. Paso 1. P ´agina de d´ıa . . . 144
C.17.Editar d´ıa. Paso 2. P ´agina de edici ´on del d´ıa . . . 144
C.18.A ˜nadir lugar de inter ´es a d´ıa. Paso 1. P ´agina de d´ıa . . . 145
C.19.A ˜nadir lugar de inter ´es a d´ıa. Paso 2. P ´agina de d´ıa . . . 145
C.20.A ˜nadir lugar de inter ´es a d´ıa. Paso 3. P ´agina de d´ıa . . . 145
C.21.Quitar lugar de inter ´es de d´ıa. Paso 1. P ´agina de d´ıa . . . 146
C.22.Quitar lugar de inter ´es de d´ıa. Paso 2. P ´agina de d´ıa . . . 146
C.23.Borrar d´ıa. Paso 1. P ´agina de d´ıa . . . 147
C.25.Crear lugar de inter ´es. Paso 1. P ´agina principal . . . 148
C.26.Crear lugar de inter ´es. Paso 2. P ´agina de creaci ´on del lugar de inter ´es . 148 C.27.Editar lugar de inter ´es. Paso 1. P ´agina de lugar de inter ´es . . . 149
C.28.Editar lugar de inter ´es. Paso 2. P ´agina de edici ´on del lugar de inter ´es . 149 C.29.B ´usqueda. P ´agina principal . . . 150
C.30.Seguir una ruta. P ´agina de ruta . . . 150
C.31.Dejar de seguir una ruta. P ´agina de ruta . . . 151
C.32.Seguir a un usuario. P ´agina de usuario . . . 151
C.33.Dejar de seguir a un usuario. P ´agina de usuario . . . 152
C.34.Valorar una ruta. P ´agina de ruta . . . 152
C.35.Borrar la valoraci ´on de una ruta. Paso 1. P ´agina de ruta . . . 153
C.36.Borrar la valoraci ´on de una ruta. Paso 2. P ´agina de ruta . . . 153
C.37.Valorar una ruta. P ´agina de lugar de inter ´es . . . 154
C.38.Borrar la valoraci ´on de un lugar de inter ´es. Paso 1. P ´agina de lugar de inter ´es . . . 154
C.39.Borrar la valoraci ´on de un lugar de inter ´es. Paso 2. P ´agina de lugar de inter ´es . . . 155
C.40.Editar perfil de usuario. Paso 1.a. P ´agina del perfil de usuario . . . 155
C.41.Editar perfil de usuario. Paso 1.b. P ´agina principal . . . 156
C.42.Editar perfil de usuario. Paso 2. P ´agina de edici ´on del perfil de usuario . 156 C.43.Eliminar perfil de usuario. Paso 1. P ´agina de perfil de usuario . . . 156
´Indice de cuadros
´Indice de C ´odigos
5.1. Relaci ´onsigueentre distintos usuarios . . . 20
5.2. Relaci ´onsigueentre usuarios y rutas . . . 20
5.3. Relaci ´on de composici ´on entre las clasesDiayLugarInteres . . . 20
5.4. Control de sesiones de la aplicaci ´on . . . 23
5.5. Implementaci ´on del m ´etodoclean()en la claseUsuarioForm . . . 24
7.1. Clase para el formulario de creaci ´on/edici ´on de eventos . . . 32
7.2. Control de sesiones de la aplicaci ´on . . . 34
8.1. Control de sesiones de la aplicaci ´on . . . 38
9.1. Configuraci ´on delemail en el ficherosettings.py . . . 42
9.2. Borrado de d´ıas as´ıncrono . . . 44
9.3. A ˜nadido de valoraciones as´ıncrono . . . 44
CAP´ITULO
1
Introducci ´
on
1.1.
Motivaci ´
on
A d´ıa de hoy nos encontramos con m ´ultiples aplicaciones muy populares que re ´unen a personas con intereses comunes. En estos grupos o foros, los usuarios participan de manera activa aportando su experiencia y su conocimiento e interaccionan entre ellos enriqueciendo la experiencia.
En este proyecto se propone el desarrollo de una aplicaci ´on web basada en viajes, pues, aunque existen muchas aplicaciones y foros sobre viajes, no existe un reposi-torio com ´un para todos los aficionados a viajar, haciendo que la b ´usqueda de rutas y lugares de inter ´es cuando se pretende ver mundo sea tediosa y el usuario pierda tiem-po de manera innecesaria. Aunque esto no solucione el problema de la infoxicaci ´on, ya que supone a ˜nadir una aplicaci ´on m ´as, se considera que supone una ayuda para que los usuarios puedan planificar sus viajes de manera m ´as concreta.
1.2.
Objetivos
1.3. Django
usuarios, lugares de inter ´es, etc ´etera).
Las principales funciones que se implementar ´an ser ´an las siguientes:
◦ Posibilidad de que el usuario a ˜nada rutas hechas por ´el.
◦ Posiblidad de que el usuario a ˜nada d´ıas a las rutas creadas.
◦ Posibilidad de que el usuario a ˜nada lugares de inter ´es.
◦ Interacci ´on entre usuarios (suscripci ´on a otros usuarios, valoraci ´on y comenta-rios sobre las rutas de otros usuacomenta-rios).
◦ Gesti ´on de rutas.
Para pr ´oximas versiones de la aplicaci ´on se propone la creaci ´on de un usuario que tenga el papel de moderador y controle que la informaci ´on dada es ver´ıdica y no es ofensiva. En este proyecto, esto se administrar ´a desde la p ´agina deladmin generada conDjango.
Respecto a la parte tecnol ´ogica, la idea principal consist´ıa en usar los servicios de
Amazon Web Services para la base de datos, el servidor, la distribuci ´on de carga, la monitorizaci ´on de rendimiento y el uso. Debido a ciertas complicaciones a la hora de subir la aplicaci ´on a Amazon Web Services finalmente se ha utilizado el servidor interno deDjangoy una base de datos local con el servidor de MySQL.
1.3.
Django
(Documentaci ´on de django, s.f.)
1.3.1.
¿Qu ´e es Django?
Djangoes unframework para el desarrollo de aplicaciones Web escrito enPython.
Antes de hablar sobre la arquitectura deDjangoes importante hacer la distinci ´on entre proyecto y aplicaci ´on enDjango.
◦ Una aplicaci ´on deDjango es un conjunto de funcionalidades.
Cap´ıtulo 1. Introducci ´on
Dentro del proyecto, se encontrar ´a un paquete con el mismo nombre que el proyec-to que incluir ´a diversos ficheros que se auproyec-togeneran al crear el proyecproyec-to. Los m ´as interesantes son:
◦ settings.py: contiene informaci ´on sobre la configuraci ´on del proyecto.
◦ urls.py: en ´el se indican todas las urls que usar ´a el proyecto Django.
◦ wsgi.py: es el fichero en el que ”se encarga”de realizar la conexi ´on con el servi-dor.
En este proyecto se desarrollar ´a una ´unica aplicaci ´on deDjango, pues no se considera que sea necesario el desarrollo de ninguna otra m ´as.
El desarrollo de aplicaciones con Django sigue el patr ´on MTV, que viene de models,
templates,views y es como se recomienda estructurar las mismas.
Las aplicaciones enDjango deben tener la siguiente estructura:
◦ El fichero en el que se implementan los modelos de la aplicaci ´on, por conven-ci ´on, es el ficheromodels.py, en ´el se crear ´an las clases, que se corresponder ´an con las tablas de la base de datos. Las clases de dicho fichero heredan de mo-dels.Model y tienen acceso a la base de datos.
◦ El fichero en el que se implementan las vistas de la aplicaci ´on, por convenci ´on, es el fichero views.py. Es importante tener en cuenta que cuando se habla de vistas en Django no se habla de interfaz gr ´afica, sino de controladores, de este modo, el ficheroviews.py ser ´a el intermediario entre los modelos y las plantillas. En el caso de esta aplicaci ´on, se ha decidido separar las vistas de cada modelo en ficheros diferentes para evitar que el ficheroviews.py sea demasiado extenso, de modo que el c ´odigo sea m ´as modular. Una vista se define como una funci ´on que toma una petici ´on (request) y devuelve una respuesta, esta respuesta puede ser de diferentes tipos.
◦ La interfaz gr ´afica de la aplicaci ´on se crear ´a en los templates (plantillas). No hay un fichero espec´ıfico para declarar estas plantillas, pues habr ´a una por cada p ´agina que tenga la aplicaci ´on. Las plantillas se crear ´an dentro de una carpeta
templatesy tendr ´an extensi ´on.html.
1.3. Django
◦ forms.py: en ´el se crean clases que heredan defoms.Form. Dichas clases pue-den utilizarse directamente en las plantillas para generar formularios de manera autom ´atica, sin tener que escribir c ´odigo enhtml. De este fichero se hablar ´a con m ´as profundidad en el apartadoDesarrollodel cap´ıtuloPrimera iteraci ´on.
◦ Ficheros para las pruebas: estos ficheros empiezan por la palabratests. En ellos se crean clases que heredar ´an de LiveServerTestCase. Esta clase inicia el ser-vidor al iniciar un test y lo apaga al finalizar el test, permitiendo el uso de herra-mientas de automatizaci ´on de pruebas.
◦ Un paquetestatic que contendr ´a diferentes paquetes hijo dentro. Cada paquete hijo contendr ´a diferentes ficheros. En este proyecto habr ´a un paquete css que contendr ´a ficheros con extensi ´on.css que se usar ´an para embellecer las planti-llas.
1.3.2.
Modelos
Como se ha comentado en la secci ´on anterior, los modelos se corresponden con las tablas de la base de datos, los atributos de un modelo son los campos de la tabla, y son los encargados de realizar la conexi ´on con la misma.
Djangodetermina el tipo de columna de la tabla de la base de datos dependiendo del tipo de datos que tenga su correspondiente atributo en el modelo. A diferencia de otros lenguajes, estos tipos de datos no son tipos simples, sino que son clases. Adem ´as, de-pendiendo del tipo de datos,Django validar ´a los datos que se intentan insertar en las columnas de la base de datos.
Adem ´as, los campos tendr ´an una serie de opciones dependiendo de si son claves pri-marias, ´unicos, si pueden ser vac´ıos, etc ´etera. Estas opciones se pasan como par ´ame-tros a la hora de definir el tipo de datos del atributo. En caso de que se cree un modelo sin clave primaria, Django autogenerar ´a un atributo autoincremental que asumir ´a el papel de la misma.
Cap´ıtulo 1. Introducci ´on
1.4.
Amazon Web Services (AWS)
“Amazon Web Services (AWS abreviado) es una colecci ´on de servicios de compu-taci ´on en la nube (tambi ´en llamados servicios web) que en conjunto forman una plata-forma de computaci ´on en la nube, ofrecidas a trav ´es de Internet por Amazon.com.”(Amazon Web Services, s.f.).
Para reducir la latencia y aumentar la robustez de los servicios, AWS se divide en 11 regiones geogr ´aficas, que son los centros de datos donde se alojan los servicios. En
Figura 1.1: Mapa de las regiones geogr ´aficas usadas por AWS
nuestro caso, debido a la cercan´ıa geogr ´afica, la aplicaci ´on se hospedar ´a en la regi ´on de Frankfurt.
Aunque AWS dispone de m ´as de media centena de servicios, en este trabajo de fin de grado se explicar ´an aquellos que se ten´ıa intenci ´on de utilizar a la hora de crear y lanzar el proyecto desarrollado. Los servicios investigados han sido:
◦ Elastic Beanstalk (EB): para administrar las aplicaciones. Es un PaaS que per-mite implementar y administrar aplicaciones web en la nube de AWS. Adem ´as, proporciona una serie de servicios para facilitar la labor de los desarrolladores.
1.5. Bootstrap
de cada cliente.
◦ Identity and Access Management (IAM): para el control de acceso a los servicios. “Con IAM es posible dar permiso a otros usuarios para que administren otros recursos propios de tu cuenta de AWS sin necesidad de compartir contrase ˜nas”. (What Is IAM?, s.f.)
◦ Relational Database Service (RDS): para la base de datos de la aplicaci ´on.
◦ Auto Scaling: para el autoescalado de EC2. Auto Scaling permite incrementar o reducir el n ´umero de instancias activas de EC2 dependiendo del n ´umero de peticiones que reciba el servidor.
◦ Elastic Load Balancing: para el balanceado de carga.
◦ Virtual Private Cloud (VPC): que permite el acceso al servidor a trav ´es de una red privada.
1.5.
Bootstrap
CAP´ITULO
2
Requisitos
2.1.
Descripci ´
on de participantes y usuarios
2.1.1.
Perfiles de usuario
Usuario
Representante Usuario
Descripci ´on Podr ´a llevar a cabo operaciones de gesti ´on de rutas tales como la creaci ´on, modificaci ´on, borrado, visua-lizaci ´on o valoraci ´on de las mismas. Tambi ´en podr ´a crear, editar, visualizar y eliminar d´ıas dentro de las rutas previamente creadas, adem ´as de crear, visuali-zar, editar y valorar lugares de inter ´es.
Tipo No hay un tipo de usuario definido.
Responsabilidades La responsabilidad del usuario con el producto es, meramente, realizar un uso correcto del mismo. Criterio de ´exito Permite que el resto de usuarios tengan informaci ´on
2.2. Requisitos funcionales
2.2.
Requisitos funcionales
1. Gesti ´on del perfil de usuario: el usuario podr ´a gestionar su perfil de usuario, pu-diendo registrarse, acceder al sistema, recuperar su contrase ˜na, salir del siste-ma, modificar el perfil y borrarlo.
a) Registro: el usuario podr ´a registrarse en el sistema introduciendo los datos necesarios.
b) Acceso: el usuario podr ´a acceder al sistema mediante un nombre de usuario y una contrase ˜na.
c) Recuperaci ´on de la contrase ˜na: el usuario podr ´a recuperar su contrase ˜na en caso de haberla olvidado.
d) Salida del sistema: el usuario podr ´a salir del sistema cerrando la sesi ´on.
e) Modificaci ´on del perfil: el usuario podr ´a modificar su perfil.
f) Borrado del perfil: el usuario podr ´a eliminar su perfil.
2. Gesti ´on de d´ıas: el usuario podr ´a crear nuevos d´ıas, visualizarlos, editarlos, bo-rrarlos, a ˜nadir y quitar lugares de inter ´es a d´ıas.
a) Creaci ´on de d´ıas: el usuario podr ´a crear un nuevo d´ıa dentro de una ruta espec´ıfica creada previamente por ´el.
b) Visualizaci ´on de d´ıas: el usuario podr ´a visualizar los d´ıas que est ´en creados en el sistema.
c) Modificaci ´on de d´ıas: el usuario podr ´a modificar los datos relativos a un d´ıa creado previamente por ´el.
d) Borrado de d´ıas: el usuario podr ´a borrar un d´ıa creado previamente por ´el.
e) A ˜nadido de lugares de inter ´es a d´ıas: el usuario podr ´a a ˜nadir lugares de in-ter ´es previamente creados a los d´ıas de sus rutas.
f) Borrado de lugares de inter ´es en d´ıas: el usuario podr ´a quitar lugares de in-ter ´es que han sido previamente a ˜nadidos a un d´ıa creado por ´el.
3. Gesti ´on de rutas: el usuario podr ´a crear nuevas rutas, visualizarlas, editarlas, borrarlas, seguir rutas, dejar de seguir rutas, valorarlas, eliminar valoraciones hechas en rutas y buscar rutas en el sistema.
Cap´ıtulo 2. Requisitos
b) Visualizaci ´on de rutas: el usuario podr ´a visualizar las rutas que est ´en crea-das en el sistema.
c) Modificaci ´on de rutas: el usuario podr ´a modificar informaci ´on relativa a una ruta creada previamente por ´el.
d) Borrado de rutas: el usuario podr ´a borrar una ruta creada previamente por ´el.
e) Seguimiento de rutas: el usuario podr ´a seguir rutas creadas por otros usua-rios.
f) Cancelaci ´on del seguimiento de rutas: el usuario podr ´a dejar de seguir ru-tas que previamente segu´ıa.
g) Valoraci ´on de rutas: el usuario podr ´a valorar las rutas creadas en el sistema indicando una puntuaci ´on y haciendo un comentario.
h) Borrado de valoraciones de rutas: el usuario podr ´a eliminar valoraciones de rutas previamente hechas por ´el.
i) B ´usqueda de rutas: el usuario podr ´a realizar b ´usquedas sobre rutas.
4. Gesti ´on de usuarios: el usuario podr ´a seguir a otros usuarios, dejar de seguir usuarios, buscar usuarios y visualizar perfiles de usuario.
a) Seguimiento de usuarios: el usuario podr ´a seguir a otros usuarios que se encuentren registrados en el sistema.
b) Cancelaci ´on del seguimiento de usuarios: el usuario podr ´a dejar de seguir usuarios que previamente segu´ıa.
c) B ´usqueda de usuarios: el usuario podr ´a realizar b ´usquedas sobre usuarios.
d) Visualizaci ´on del perfil: el usuario podr ´a ver perfiles de usuarios existentes en el sistema.
5. Gesti ´on de lugares de inter ´es: el usuario podr ´a crear, editar y visualizar lugares de inter ´es, adem ´as de valorarlos, eliminar valoraciones previamente hechas en lugares de inter ´es y buscar lugares de inter ´es.
a) Creaci ´on de lugares de inter ´es: el usuario podr ´a crear nuevos lugares de inter ´es.
b) Visualizaci ´on de lugares de inter ´es: el usuario podr ´a visualizar lugares de inter ´es previamente creados en el sistema.
in-2.3. Requisitos no funcionales
ter ´es sin necesidad de ser el creador de los mismos.
d) Valoraci ´on de lugares de inter ´es: el usuario podr ´a valorar los lugares de in-ter ´es creados en el sistema indicando una puntuaci ´on y haciendo un co-mentario.
e) Borrado de valoraciones de lugares de inter ´es: el usuario podr ´a eliminar va-loraciones de lugares de inter ´es previamente hechas por ´el.
f) B ´usqueda de lugares de inter ´es: el usuario podr ´a realizar b ´usquedas sobre lugares de inter ´es.
6. Monitorizaci ´on de acciones: el sistema monitorizar ´a las acciones que los usua-rios realicen sobre las rutas, incluyendo la creaci ´on y modificaci ´on de las mis-mas, a ˜nadido de d´ıas, modificado de d´ıas, a ˜nadido de lugares de inter ´es a d´ıas y borrado de lugares de inter ´es de d´ıas.
2.3.
Requisitos no funcionales
REQUISITOS DE ASPECTO
RNF 1. El dise ˜no de la aplicaci ´on debe serresponsive: para mejorar la experiencia del usuario, la aplicaci ´on debe poder adaptar su dise ˜no a cualquier tipo de pantalla.
REQUISITOS DE FACILIDAD DE USO Y APRENDIZAJE
RNF 2. La aplicaci ´on debe ser f ´acil de usar: para mayor comodidad del usuario, el pro-grama debe ser sencillo e intuitivo.
RNF 3. La aplicaci ´on debe ser adaptable: debe permitir a ˜nadir funcionalidades.
RNF 4. La aplicaci ´on debe poder internacionalizarse: la aplicaci ´on podr ´a traducirse a varios idiomas.
REQUISITOS OPERACIONALES
Cap´ıtulo 2. Requisitos
RNF 6. La aplicaci ´on debe estar desarrollada en Django.
2.4.
Requisitos de documentaci ´
on
MANUAL DE USUARIO
La aplicaci ´on deber ´a incluir un manual de usuario que indique, en un lenguaje no t ´ecnico, c ´omo utilizar la misma.
GU´IAS DE INSTALACI ´ON Y CONFIGURACI ´ON
CAP´ITULO
3
Dise ˜
no
3.1.
Diagrama de clases
Inicialmente, la implementaci ´on del proyecto se hab´ıa pensado con dos tipos de usua-rios: el usuario y el administrador. El diagrama de clases inicial era el diagrama de clases de la figura 3.1.
En vista de que no era posible verificar la identidad del usuario cuyo tipo de perfil esAdministradorLugarInteres, se decidi ´o hacer diversas modificaciones, quedando el siguiente diagrama de clases (figura 3.2):
Como se puede observar, se han eliminado las clases AdministradorLugarInteres y
Evento, y la relaci ´on entre Usuario y LugarDeInteres pasa de llamarsesigue a crea. El porqu ´e de estos cambios se explicar ´a m ´as detalladamente en el cap´ıtulo 9,4a ite-raci ´on.
3.1. Diagrama de clases
Cap´ıtulo 3. Dise ˜no
CAP´ITULO
4
Visi ´
on de conjunto
Para facilitar la comprensi ´on de este documento, se hace necesario explicar la visi ´on de conjunto de la aplicaci ´on.
En este desarrollo de la aplicaci ´on se implementa un ´unico tipo de usuario, que podr ´a crear rutas tur´ısticas, d´ıas dentro de las mismas y a ˜nadir lugares de inter ´es a estos.
Las rutas estar ´an compuestas por d´ıas, cada d´ıa incluir ´a una serie de lugares de in-ter ´es localizados en un mapa y listados por orden en la p ´agina de informaci ´on de cada d´ıa.
En la p ´agina principal de la aplicaci ´on se mostrar ´an las rutas a las que est ´a suscrito un usuario y las rutas creadas por ´el, adem ´as de untimelineque mostrar ´a los cambios m ´as recientes que han realizado los usuarios seguidos por el usuario.
El usuario de la aplicaci ´on, despu ´es de haber accedido al sistema, podr ´a realizar las siguientes acciones:
◦ Crear, editar, visualizar y eliminar rutas.
◦ A ˜nadir d´ıas a rutas.
◦ A ˜nadir y quitar lugares de inter ´es a d´ıas. Ya que, como se ha comentado ante-riormente, un d´ıa incluye una serie de lugares de inter ´es.
◦ Crear, visualizar y editar lugares de inter ´es.
◦ Seguir o dejar de seguir rutas.
◦ Seguir o dejar de seguir a usuarios.
◦ Visualizar perfiles de usuarios.
◦ Valorar rutas y lugares de inter ´es.
◦ Buscar rutas, usuarios y lugares de inter ´es.
◦ Editar o eliminar su perfil de usuario.
CAP´ITULO
5
Primera iteraci ´
on
5.1.
Requisitos implementados
En la primera iteraci ´on del desarrollo del proyecto se han decidido implementar los siguientes requisitos funcionales:
◦ Registro.
◦ Acceso.
◦ Creaci ´on de rutas.
◦ Visualizaci ´on de rutas.
◦ Modificaci ´on de rutas.
◦ Borrado de rutas.
◦ Creaci ´on de d´ıas.
◦ Visualizaci ´on de d´ıas.
◦ Modificaci ´on de d´ıas.
◦ Borrado de d´ıas.
5.2. Desarrollo
5.2.
Desarrollo
5.2.1.
Modelos
Al ser el primer desarrollo que se hace del proyecto, ha sido necesaria la implementa-ci ´on de los modelos de Django. La implementaimplementa-ci ´on de modelos de la primera iteraimplementa-ci ´on se hizo acorde al primer diagrama de clases que se dise ˜n ´o (Figura 4.1), habiendo su-frido modificaciones en iteraciones posteriores.
Aparte de las clases que se ven en dicho diagrama, se implementaron las clases
RelacionSeguidos, RelacionRutasSeguidas y RelacionDiaLugarInteres; estas clases se utilizan para implementar las relaciones M:M que hay entre algunas tablas. De este modo, la clase RelacionSeguidos se corresponde con la relaci ´on reflexivasigue
entre distintos usuarios; la claseRelacionRutasSeguidasimplementa la relaci ´onsigue
entre usuarios y rutas; y la clase RelacionDiaLugarInteres representa la relaci ´on de composici ´on entre la clase Dia y la clase LugarInteres. La implementaci ´on qued ´o de la siguiente manera:
C ´odigo 5.1: Relaci ´onsigueentre distintos usuarios
class RelacionSeguidos(models.Model):
seguidor = models.ForeignKey(Usuario, related_name=’seguidor’)
seguido = models.ForeignKey(Usuario, related_name=’seguido’)
class Meta:
unique_together = (’seguidor’, ’seguido’)
C ´odigo 5.2: Relaci ´on sigueentre usuarios y rutas
class RelacionRutasSeguidas(models.Model):
seguidorRuta = models.ForeignKey(Usuario, related_name=’seguidorRuta’)
ruta = models.ForeignKey(Ruta, related_name=’ruta’)
class Meta:
unique_together = (’seguidorRuta’, ’ruta’)
C ´odigo 5.3: Relaci ´on de composici ´on entre las clasesDiayLugarInteres
class RelacionDiaLugarInteres(models.Model):
lugaresInteres = models.ForeignKey(LugarInteres,
Cap´ıtulo 5. Primera iteraci ´on
dia = models.ForeignKey(Dia, related_name=’dia’)
class Meta:
unique_together = (’lugaresInteres’,’dia’)
Cabe destacar el uso de la clase internaMetadentro de cada una de las clases de la relaci ´on con el objetivo de definir los metadatos del modelo, en este caso, el objetivo principal de los metadatos es evitar que haya objetos duplicados, esto se indica en el atributounique together de dicha clase.
En la claseRutase ha implementado una funci ´on llamadarutasSeguidasUsuarioa la que se le pasa un par ´ametro usuario y que devolver ´a todas las rutas que sigue ese usuario.
Finalmente, en la clase Dia se ha implementado una funci ´on dias ruta a la que se le pasa como par ´ametro ruta, esta funci ´on devolver ´a una lista con los d´ıas que tiene asociada una ruta.
Tras desarrollar los modelos, es muy importante realizar las migraciones de modo que los modelos pasen a ser entidades en la base de datos. Desde la consola de coman-dos (y estando en el directorio ra´ız del proyecto), es necesario ejecutar los siguientes comandos:
python manage.py makemigrations
Lo que hace este comando es comparar las entidades que hay actualmente en la base de datos con los nuevos modelos y crea un archivo con las migraciones pertinentes. Despu ´es de obtener dicho archivo, para realizar los cambios en la base de datos, habr ´a que ejecutar el comando:
python manage.py migrate
5.2.2.
Vistas
modifica-5.2. Desarrollo
ciones y hacer m ´as sencilla la lectura del c ´odigo.
views usuario.py
En este fichero se implementan las vistas necesarias para desarrollar los casos de uso relacionados con el perfil del usuario. Se ha estimado necesario desarrollar los siguientes m ´etodos:
◦ init(request): carga la p ´agina inicial de la aplicaci ´on (login.html) con su respectivo formulario, tambi ´en valida que los datos introducidos en el formulario pertenecen a un usuario registrado en el sistema, y que son correctos. La URL asociada a esta vista es una URL vac´ıa, de modo que sea la primera p ´agina que se cargue a la hora de acceder a la aplicaci ´on en caso de no tener una sesi ´on iniciada en el sistema.
◦ registro(request): carga una p ´agina con un formulario para el registro de un nuevo usuario en el sistema. Tambi ´en se encarga de validar que los campos obligato-rios han sido rellenados y que no existan usuaobligato-rios con el mismo alias o email que se introduce para crear una nueva cuenta y una vez validados los datos (siendo estos correctos), crea un nuevo perfil de usuario.
Se puede observar que una vez creado el usuario, el alias del mismo se almace-na en ualmace-na variable de sesi ´on. Se ha decidido usar variables de sesi ´on en lugar de cookies porque estas ´ultimas no se consideran seguras si no se env´ıan por HTTPS, siendo susceptibles a diversos ataques, como pueden ser ataques de tiposnooping1yMan-in-the-middle. Estos problemas se solucionan (en gran par-te) con el uso de sesiones, pues al almacenar toda la informaci ´on relevante en el servidor, evitan el env´ıo constante de informaci ´on como ocurre con lascookies.
◦ inicio(request): esta vista carga la p ´agina de principal de la aplicaci ´on con los datos de las rutas pertenecientes al usuario que est ´a almacenado en la variable de sesi ´on. En caso de no haber ning ´un usuario almacenado en la variable de sesi ´on, se cargar ´a la p ´agina dellogin.
views ruta.py
En este fichero se han implementado las vistas necesarias para hacer el CRUD de la clase Ruta. A grandes rasgos, se puede comprobar que todas las vistas contienen un fragmento de c ´odigo com ´un, este c ´odigo controla que el usuario haya accedido
Cap´ıtulo 5. Primera iteraci ´on
al sistema; en caso de que no haya accedido, la aplicaci ´on redirigir ´a al usuario a la p ´agina delogin. El c ´odigo es el siguiente:
C ´odigo 5.4: Control de sesiones de la aplicaci ´on
if "usuario" in request.session:
usuario = models.Usuario.objects.filter(alias = request.session["usuario"])[0]
if usuario == None:
form = forms.RegistroForm()
return render(request, ’login.html’, {’form’: form})
else:
# Implementacion de la vista
else:
form = forms.RegistroForm()
return render(request, ’login.html’, {’form’: form})
Este c ´odigo de control de sesiones va a estar presente pr ´acticamente en todas las vis-tas de la aplicaci ´on, a excepci ´on de aquellas relativas a la creaci ´on de nuevos usuarios o al registro de los mismos.
Tambi ´en se puede observar que en las vistas editarRuta(request, id ruta)y borrarRu-ta(request, id ruta) se comprueba que el usuario que intenta realizar la acci ´on sea el creador de dicha ruta; en caso contrario, se le redirigir ´a a la p ´agina principal de la aplicaci ´on.
views dia.py
5.2. Desarrollo
5.2.3.
Formularios
Debido a las facilidades que ofrece Django para la creaci ´on de formularios, se ha decidido desarrollar los mismos utilizando el fichero forms.py, en este fichero se han implementado clases que heredan de forms.Form cuyos atributos se corresponder ´an con los campos de los formularios que se mostrar ´an al ejecutar los ficheros.html.
En este fichero destaca la definici ´on de un m ´etodoclean()dentro de la clase Usuario-Form. Este m ´etodo viene heredado de forms.Form y se utiliza para validar los datos recibidos desde el formulario; en este caso, valida que los campos que hacen referen-cia a la contrase ˜na y alemail coincidan.
C ´odigo 5.5: Implementaci ´on del m ´etodoclean()en la claseUsuarioForm
def clean(self):
if (self.cleaned_data.get(’password’) !=
self.cleaned_data.get(’confirmacionPassword’)):
msg = ’Las contrasenas no coinciden’
self.add_error(’confirmacionPassword’, msg)
if (self.cleaned_data.get(’email’) !=
self.cleaned_data.get(’confirmacionEmail’)):
msg = ’Los emails no coinciden’
self.add_error(’confirmacionEmail’, msg)
5.2.4.
Templates
Dentro del paquete templates se encuentran los ficheros de la interfaz gr ´afica de la aplicaci ´on, es decir, los ficheros con extensi ´on .html. En esta iteraci ´on se han imple-mentado los siguientes:
◦ login.html: en ´el se ha implementado la p ´agina para el login. Como se puede comprobar, se muestra un formulario. El formulario usado no se especifica en este fichero sino que se enviar ´a desde la vista. En este caso, el formulario mos-trado esRegistroForm. Es interesante destacar el uso de la etiquetacsrf token
justo despu ´es de la apertura del formulario. Esta etiqueta se usa para evitar
Cross Site Request Forgeries. Esta etiqueta se usa en formularios POST que apuntan a URLs internas.
Cap´ıtulo 5. Primera iteraci ´on
a la delogin.html.
◦ En el ficheroinicio.html viene implementada la p ´agina principal de la aplicaci ´on. En ella se muestra un listado con enlaces a las rutas creadas por el usuario de la sesi ´on.
◦ Los ficherosruta.html ydia.html muestran la informaci ´on correspondiente a una ruta y a un d´ıa, respectivamente.
Para el dise ˜no gr ´afico de la interfaz gr ´afica (archivos.css), es necesario crear un nue-vo paquete llamadostatic en el que se guardar ´an todos los archivos est ´aticos (CSS,
JavaScript, im ´agenes, etc); dentro de este paquete es necesario crear un nuevo pa-quete llamadocsspara guardar los archivos de este tipo. Para relacionar los .csscon los.html, habr ´a que escribir la siguiente l´ınea de c ´odigo dentro de la etiqueta<head> del archivo.html:
<link rel="stylesheet" href="{% static ’css/formularios.css’ %}">
Adicionalmente, se han usado los siguientes componentes deBootstrap:
◦ Navbar para la barra que se encuentra en la parte superior de todas las p ´aginas de la aplicaci ´on una vez se ha iniciado sesi ´on.
◦ Para hacer m ´as visuales algunas opciones, se han utilizado algunosGlyphicons, como pueden ser el l ´apiz que se encuentra al lado del textoEditar o la papelera que se encuentra al lado del textoBorrar.
CAP´ITULO
6
Segunda iteraci ´
on
6.1.
Requisitos implementados
En esta iteraci ´on se han decidido implementar los siguientes requisitos funcionales:
◦ Salida del sistema.
◦ Seguimiento de rutas.
◦ Cancelaci ´on del seguimiento de rutas.
◦ B ´usqueda de rutas.
◦ Seguimiento de usuarios.
◦ Cancelaci ´on del seguimiento de usuarios.
◦ B ´usqueda de usuarios.
◦ Visualizaci ´on del perfil.
◦ Modificaci ´on del perfil.
◦ Borrado del perfil.
6.2. Desarrollo
6.2.
Desarrollo
6.2.1.
Vistas
En esta iteraci ´on los cambios m ´as notables se han producido en las vistas, por lo que nos centratemos en las mismas.
views usuario.py
Se han a ˜nadido los siguientes m ´etodos al fichero:
◦ logout(request): este m ´etodo se encarga de limpiar la variable de sesi ´on que almacena el nombre de usuario, terminando as´ı con la sesi ´on del mismo e impi-diendo que pueda acceder a la aplicaci ´on.
◦ miPerfil(request): este m ´etodo se encarga de cargar la informaci ´on del usuario que tiene una sesi ´on iniciada en el sistema en una p ´agina. Adem ´as de la infor-maci ´on b ´asica del perfil, tambi ´en muestra inforinfor-maci ´on sobre las rutas creadas, las rutas seguidas y los usuarios seguidos. Adem ´as, en ella se da la opci ´on al usuario de editar o eliminar el perfil.
◦ editarPerfil(request): carga un formulario con la informaci ´on b ´asica del usuario que tiene iniciada sesi ´on en el sistema para que este la modifique seg ´un estime conveniente.
◦ borrarPerfil(request): elimina el perfil del usuario que tiene iniciada sesi ´on en el sistema, limpiando tambi ´en la variable de sesi ´on que almacena el nombre del usuario.
◦ perfil(request, id usuario): carga el perfil de un usuario registrado en el sistema. La ´unica diferencia con la vista miPerfil(request) es que a esta no se le pasa como par ´ametro elid usuario, ya que no es necesario.
◦ seguirUsuario(request, id usuario): esta vista a ˜nade un usuario seleccionado a la lista de seguidos del usuario que tiene iniciada sesi ´on en el sistema.
Cap´ıtulo 6. Segunda iteraci ´on
views ruta.py
La vista m ´as destacable del fichero views ruta.py es busqueda(request). En ella, se toma el valor de un formulario de tipo GET y se buscan rutas y usuarios atendiendo a los siguientes criterios:
◦ El t´ıtulo de la ruta contiene la consulta.
◦ La descripci ´on del a ruta contiene la consulta.
◦ El t´ıtulo o la descripci ´on del d´ıa contienen la consulta.
◦ El creador de la ruta contiene la consulta.
◦ El alias del usuario contiene la consulta.
Esta vista redirigir ´a a una nueva p ´agina que mostrar ´a dos pesta ˜nas: una pesta ˜na mos-trar ´a las rutas coincidentes encontradas y la otra, los usuarios.
Tambi ´en se han implementado las vistasseguirRuta(request, id ruta)y dejarDeSegui-rRuta(request, id ruta), las cuales no ser ´an comentadas pues son muy similares a las vistasseguirUsuario(request, id usuario)ydejarDeSeguirUsuario(request, id usuario).
Finalmente, se han modificado las vistas anteriormente implementadas, en ellas ahora se comprueba si el usuario sigue la ruta que cargan.
6.2.2.
Templates
En esta iteraci ´on se ha a ˜nadido eltemplate busqueda.html, en el que se muestran los datos relativos a la b ´usqueda realizada.
Tambi ´en se han implementadotemplates relativos al perfil de usuario, como son per-fil.html, en el que se muestran los datos de un usuario, y editarPerfil.html, para la modificaci ´on de los datos de un usuario.
6.3. Pruebas
Una modificaci ´on bastante simple pero a la vez bastante significativa es el despliegue de unalert usandoJavaScript para confirmar el borrado de d´ıas y rutas.
6.3.
Pruebas
CAP´ITULO
7
Tercera iteraci ´
on
7.1.
Requisitos implementados
En esta iteraci ´on del desarrollo del proyecto se han implementado una serie de requi-sitos funcionales que no se encuentran en el cap´ıtulo 3. Esto se debe a que la lista de requisitos del cap´ıtulo 2 no es la lista inicial y ha sufrido modificaciones a lo largo del desarrollo.
En este caso, exist´ıa otro rol de usuario llamadoAdministrador, que se encargaba de crear, editar, modificar y borrar lugares de inter ´es creados por ´el. Adem ´as, pod´ıa crear, modificar y borrar eventos asociados a los lugares de inter ´es creados por ´el.
A continuaci ´on se enumeran y explican los requisitos que se implementaron en esta iteraci ´on:
◦ Registro de administrador: el administrador podr ´a registrarse en el sistema intro-duciendo los datos necesarios.
◦ Acceso de administrador: el administrador podr ´a acceder al sistema indicando que es un administrador e introduciendo un nombre de usuario y una contrase ˜na.
◦ Salida del sistema del administrador: el administrador podr ´a salir del sistema ce-rrando sesi ´on.
7.2. Desarrollo
inter ´es.
◦ Visualizaci ´on de lugares de inter ´es: el usuario y el administrador podr ´an visuali-zar los lugares de inter ´es que est ´en creados en el sistema.
◦ Modificaci ´on de lugares de inter ´es: el administrador podr ´a modificar la informa-ci ´on relativa a un lugar de inter ´es creado previamente por ´el.
◦ Borrado de lugares de inter ´es: el administrador podr ´a borrar un lugar de inter ´es previamente creado por ´el.
◦ Creaci ´on de eventos: el administrador podr ´a crear un nuevo evento dentro de un lugar de inter ´es espec´ıfico creado por ´el.
◦ Visualizaci ´on de eventos: el usuario y el administrador podr ´an visualizar los even-tos que est ´en creados en el sistema.
◦ Modificaci ´on de eventos: el administrador podr ´a modificar informaci ´on relativa a un evento creado previamente por ´el.
◦ Borrado de eventos: el administrador podr ´a borrar un evento creado previamente por ´el.
La especificaci ´on de los casos de uso, al igual que en los cap´ıtulos anteriores, vendr ´a hecha en elAnexo A.
7.2.
Desarrollo
7.2.1.
Formularios
Se hace necesario mencionar las modificaciones en el fichero forms.py antes de ex-plicar las modificaciones en las vistas.
En primer lugar, se crearon dos nuevas clases, una para el formulario de creaci ´on y edici ´on del lugar de inter ´es, y otra para el formulario de creaci ´on y edici ´on del evento. Se hace interesante mostrar el c ´odigo del formulario implementado para la creaci ´on y edici ´on de eventos, pues ha sido eliminado en posteriores iteraciones (el porqu ´e de estos cambios viene explicado en el siguiente cap´ıtulo), por lo que no es posible encontrarla en el c ´odigo de la aplicaci ´on:
Cap´ıtulo 7. Tercera iteraci ´on
class EventoForm(forms.Form):
nombre = forms.CharField(max_length=100, label="Nombre")
descripcion = forms.CharField(max_length=1000, widget=forms.Textarea)
inicio = forms.DateField(initial=datetime.date.today())
fin = forms.DateField(initial=datetime.date.today())
precio = forms.DecimalField(max_digits=8, decimal_places=2)
Tambi ´en se hace necesario comentar que el campo horario de la clase LugarInteres-Form sea de tipo CharField, en lugar de ser de tipoTimeField, se ha decidido imple-mentar de esta manera para dar m ´as libertad al administrador del lugar de inter ´es, pues los horarios pueden variar dependiendo de si es fin de semana, festivo o laboral.
Se a ˜nadi ´o tambi ´en un campo adminde tipoBooleanField a la claseUsuarioForm, de manera que se puedan crear usuarios con el rol de administrador de lugares de inter ´es. Asimismo, tambi ´en se a ˜nadi ´o un campo administrador, tambi ´en de tipo BooleanField
a la claseRegistroFormpara que el administrador de lugares de inter ´es pudiera iniciar sesi ´on.
7.2.2.
Vistas
Las vistas implementadas en iteraciones anteriores fueron modificadas para evitar que el administrador de lugares de inter ´es accediera a p ´aginas que no le estaban permiti-das, como eran la p ´agina de inicio de usuario, las p ´aginas de creaci ´on, visualizaci ´on, modificaci ´on y borrado de la ruta, la p ´aginas de creaci ´on, visualizaci ´on, modificaci ´on y borrado del d´ıa y la p ´agina de b ´usqueda. De este modo, el administrador de lugares de inter ´es solo pod´ıa acceder a las p ´aginas de creaci ´on, visualizaci ´on, modificaci ´on y borrado de lugares de inter ´es y eventos, adem ´as de la p ´agina de inicio del adminis-trador de lugares de inter ´es, que mostraba ´unicamente los lugares de inter ´es creados por el mismo.
7.2. Desarrollo
views admin.py
En este fichero solo se ha implementado una ´unica vista: inicioAdmin(request) esta vista cargar´ıa todos los lugares de inter ´es (ordenados por nombre) creados por el administrador que tiene iniciada sesi ´on en el sistema y los mostrar´ıa en su p ´agina principal de la aplicaci ´on.
views lugar interes.py
Se puede comprobar que en todas las vistas de este fichero se repite el mismo frag-mento de c ´odigo:
C ´odigo 7.2: Control de sesiones de la aplicaci ´on
if "admin" in request.session:
admin = models.Administrador.objects.filter(alias = request.session["admin"])[0]
if admin == None:
form = forms.RegistroForm()
return render(request, ’login.html’, {’form’: form})
else:
# Implementacion de la vista
else:
form = forms.RegistroForm()
return render(request, ’login.html’, {’form’: form})
Este c ´odigo impide que los usuarios que no hayan iniciado sesi ´on en el sistema pue-dan ver las p ´aginas del mismo. Y, aunque hayan iniciado sesi ´on, si no son de tipo
Administrador, tampoco podr ´an acceder a ciertas p ´aginas de la aplicaci ´on.
Cap´ıtulo 7. Tercera iteraci ´on
views evento.py
La implementaci ´on de las vistas de este fichero es similar a la del ficheroviews lugar interes.py. En ´el se desarrollan las vistas necesarias para hacer un CRUD de un evento dentro de
un lugar de inter ´es. Al igual que en las vistas desarrolladas en el fichero explicado en el apartado anterior, se comprueba que el administrador tiene una sesi ´on iniciada en el sistema. Tambi ´en se comprueba que el administrador que intenta crear un evento en un lugar de inter ´es sea el mismo que cre ´o el lugar de inter ´es.
7.2.3.
Templates
En esta iteraci ´on se han implementado los siguientestemplates:
◦ En el fichero inicioAdmin.html se implementa la p ´agina principal de la aplica-ci ´on de cara al administrador. En ella ´unicamente se muestra un listado con los lugares de inter ´es creados por ´el.
◦ En los ficheros crearEvento.html y crearLugarInteres.html se implementan las p ´aginas que muestran los formulariosEventoForm yLugarInteresForm respecti-vamente.
CAP´ITULO
8
Cuarta iteraci ´
on
8.1.
Requisitos implementados
Debido a que no es posible verificar que el usuario registrado como administrador de lugares de inter ´es sea realmente alguien que tenga relaci ´on con dichos lugares de in-ter ´es, se ha decidido eliminar el rol de administrador. De este modo, todos los usuarios podr ´an crear y editar cualquier lugar de inter ´es. La idea es que haya la mayor infor-maci ´on posible sobre los lugares de inter ´es, y se puedan corregir los errores. Para futuras versiones se propone la creaci ´on de un usuario con rol moderador que ser ´a el encargado de confirmar que la informaci ´on de los lugares de inter ´es es correcta.
Teniendo esto en cuenta, los requisitos funcionales desarrollados en esta iteraci ´on han sido los siguientes:
◦ Creaci ´on de lugares de inter ´es.
◦ Visualizaci ´on de lugares de inter ´es.
◦ Modificaci ´on de lugares de inter ´es.
◦ B ´usqueda de lugares de inter ´es.
◦ Valoraci ´on de rutas.
◦ Borrado de valoraciones de rutas.
8.2. Desarrollo
◦ Borrado de valoraciones de lugares de inter ´es.
◦ A ˜nadido de lugares de inter ´es a d´ıas.
8.2.
Desarrollo
8.2.1.
Modelos
Como se ha comentado en el apartado anterior, no es posible verificar que el admi-nistrador de lugares de inter ´es sea una persona que realmente tiene una relaci ´on con dichos lugares de inter ´es, por lo que se ha decidido eliminar este tipo de usuario, eli-minando as´ı este modelo.
Eliminado el administrador, no tiene sentido que los lugares de inter ´es contengan eventos, pues los usuarios no tienen por qu ´e saber si en un lugar se va a celebrar algo, por lo que tambi ´en se ha decidido eliminar este modelo.
8.2.2.
Vistas
En esta iteraci ´on se han modificado las vistas relativas a los lugares de inter ´es y se han a ˜nadido vistas para las valoraciones.
Con respecto a las modificaciones en las vistas relativas a los lugares de inter ´es se puede comprobar que el c ´odigo que antes era com ´un en las mismas ha sido reempla-zado por el siguiente:
C ´odigo 8.1: Control de sesiones de la aplicaci ´on
if "usuario" in request.session:
usuario = models.Usuario.objects.filter(alias = request.session["usuario"])[0]
if usuario == None:
form = forms.RegistroForm()
return render(request, ’login.html’, {’form’: form})
else:
# Implementacion de la vista
else:
Cap´ıtulo 8. Cuarta iteraci ´on
return render(request, ’login.html’, {’form’: form})
Como se puede observar, en estas vistas no se comprueba que el usuario sea el creador del lugar de inter ´es, sino que ´unicamente se comprueba que haya un usuario registrado en el sistema.
En el ficheroviews ruta.py se han producido varias modificaciones:
◦ Se ha modificado la vista busqueda(request) para que se busquen lugares de inter ´es cuyo t´ıtulo o localidad contengan la consulta.
◦ Se han a ˜nadido las vistas addValoracion(request) y borrarValoracion(request, id valoracion) para a ˜nadir una valoraci ´on a una ruta, o borrar una valoraci ´on he-cha en una ruta, respectivamente.
◦ Adem ´as, cuando se carga la p ´agina de una ruta, se carga tambi ´en una lista con las valoraciones asociadas a la ruta.
◦ Se ha implementado una funci ´on para calcular la valoraci ´on media de una ruta.
En el ficheroviews lugar interes.py adem ´as de implementar las vistas para el a ˜nadido y borrado de valoraciones de los mismos (similares a las vistas de a ˜nadido y borrado de valoraciones de las rutas), cabe destacar la vista buscar lugares interes(request). Contra todo pron ´ostico, esta vista se llama desde la p ´agina de informaci ´on de un d´ıa, y se utiliza para buscar lugares de inter ´es dada una localidad, y recargar ´a la p ´agina del d´ıa mostrando un listado con los lugares de inter ´es encontrados. La vista que a ˜nade dichos lugares de inter ´es al d´ıa esadd lugar interes(request).
8.2.3.
Formularios
En los formularios relativos al acceso y al registro se puede observar que se ha elimi-nado el campo que hac´ıa referencia al administrador.
Se ha a ˜nadido una nueva clase al fichero, EditarLugarInteresForm. El prop ´osito de esta clase de formulario es que el usuario no pueda modificar el nombre, la direcci ´on ni la localidad del lugar de inter ´es cuando entra en la p ´agina que muestra el formulario de edici ´on del mismo.
8.2. Desarrollo
valoraciones tanto en la p ´agina de informaci ´on de la ruta como en la del lugar de inter ´es.
8.2.4.
Templates
En esta iteraci ´on se han producido los siguientes cambios en lostemplates:
◦ Enruta.html ylugarInteres.html se han implementado los formularios de las va-loraciones y debajo se muestran las vava-loraciones relativas a la ruta o al lugar de inter ´es de los cuales se est ´a consultando la informaci ´on.
CAP´ITULO
9
Quinta iteraci ´
on
9.1.
Requisitos implementados
En esta iteraci ´on se han implementado ´unicamente dos requisitos funcionales. El peso de la misma ha reca´ıdo en el desarrollo de tareas as´ıncronas, validaciones de datos en los formularios e internacionalizaci ´on. Los requisitos implementados han sido los siguientes:
◦ Borrado de lugares de inter ´es en d´ıas.
◦ Recuperaci ´on de la contrase ˜na.
Tambi ´en se ha modificado la creaci ´on de lugares de inter ´es, ahora se comprueba que no existe un lugar de inter ´es con el mismo nombre en la misma ciudad.
9.2.
Desarrollo
9.2.1.
Vistas
views usuario.py
9.2. Desarrollo
comprueba que exista un usuario con el email introducido en el formulario de recupe-raci ´on de la contrase ˜na.
En caso de que exista un usuario con el email introducido, se generar ´a una contra-se ˜na con caracteres alfanum ´ericos de longitud 10 y contra-se asignar ´a al usuario. Luego contra-se procede al env´ıo de la contrase ˜na alemail vinculado al usuario.
Para el env´ıo del email se ha utilizado la clase de Django EmailMultiAlternatives. Que se importar ´a dedjango.core.mail. Adem ´as, es necesario modificar el fichero set-tings.py y a ˜nadir la siguiente configuraci ´on:
C ´odigo 9.1: Configuraci ´on delemail en el ficherosettings.py
EMAIL_HOST = ’smtp.gmail.com’ # Servidor del e-mail, en este caso es Gmail
EMAIL_HOST_PASSWORD = ’password’
EMAIL_HOST_USER = ’[email protected]’
EMAIL_PORT = 587
EMAIL_USE_TLS = True
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
views lugar interes.html
Se ha implementado la vista removeLugarInteresEnDia(request, id lugarInteres) que permitir ´a al creador de un d´ıa quitar lugares de inter ´es previamente a ˜nadidos.
Tambi ´en se ha modificado la vistacrearLugarInteres(request) de modo que se valide que no haya ya un lugar de inter ´es con el mismo nombre y la misma localizaci ´on crea-do en el sistema.
Adem ´as, se ha a ˜nadido un m ´etodo que calcular ´a la valoraci ´on media de un lugar de inter ´es.
views ruta.py yviews dia.py
Cap´ıtulo 9. Quinta iteraci ´on
El precio del d´ıa ser ´a la suma de los precios de todos los lugares de inter ´es del mismo y el precio de la ruta ser ´a la suma del precio de sus d´ıas.
9.2.2.
Templates
Como se ha comentado anteriormente, el peso de esta iteraci ´on ha reca´ıdo en el desarrollo de operaciones as´ıncronas y el uso de la API de Google Maps, por lo que se har ´a hincapi ´e en los mismos. Al implementarse en diferentes archivos .html, se comentar ´a lo desarrollado, sin dar importancia al archivo en el que se desarrolla.
Tareas as´ıncronas
Antes de comentar el desarrollo, se hace necesario explicar qu ´e es una tarea as´ıncro-na. A grandes rasgos, en el ´ambito de la ingenier´ıa web las tareas as´ıncronas son aquellas que se ejecutan en segundo plano y evitan que la p ´agina tenga que estar refresc ´andose.
Para implementar estas tareas se ha utilizado AJAX y JQuery, aunque existen otras tecnolog´ıas como pueden ser Celery o Parsley. ¿Por qu ´e no se ha utilizadoCelery o
Parsley? Pues bien,Celery est ´a pensado para la ejecuci ´on de tareas intensivas que bloquear´ıan la aplicaci ´on en caso de no ejecutarse en segundo plano.Parsley, por otro lado, se utiliza para las validaciones de campos en formularios en tiempo real, pero se ha quedado obsoleto.
Teniendo esto en cuenta, se procede a explicar las tareas as´ıncronas desarrolladas en esta iteraci ´on:
◦ Borrado de d´ıas directamente desde la tabla que se muestra en la p ´agina de la ruta. Esta tarea se invoca en el atributoonclick dentro de la etiqueta <a> del borrado del d´ıa. Como se puede comprobar se ha eliminado el atributohref
de la misma, esto es debido a que la llamada a la vista que se hace dentro de este atributo tiene m ´as prioridad que la llamada a la tarea en JQuery, adem ´as de que no hay ning ´un inter ´es en acceder a una nueva p ´agina.
cons-9.2. Desarrollo
truida anteriormente y, en caso de ´exito en la operaci ´on, modificar ´a la p ´agina actual, en caso de fallo, lanzar ´a un mensaje de error.
C ´odigo 9.2: Borrado de d´ıas as´ıncrono
<td><a onclick="borrarDia({{dia.id}})"><span class="glyphicon
glyphicon-trash" aria-hidden="true"></span>{ % trans "Borrar" %}</a> <script type="text/javascript">
function borrarDia(id_dia){
var confirmacion = confirm(’Borrar el dia?’);
if (confirmacion == true){
var $url = "/"+id_dia+"/borrarDia/";
$.ajax({ url: $url, success: function(data){ $(’body’).html(data); }, error: function(){
alert("Error");
}
});
}
}
</script>
\label{borrado_dias_asincrono}
◦ A ˜nadido de valoraciones a rutas.(listado ??) Para realizar esta operaci ´on es necesario que la etiqueta <form>tenga un ´unico atributo, este ser ´a el atributo
id. La tarea se realizar ´a creando un objeto con el formulario en JQuery y lla-mando desde el objeto al m ´etodo submit. Dentro del m ´etodosubmit se llama al m ´etodoajax(), en el que se serializan los datos para su tratamiento, se indica si el formulario es de tipoGET oPOST y la URL de la vista en la que se tratar ´a el formulario, en este caso,/addValoracion/.
C ´odigo 9.3: A ˜nadido de valoraciones as´ıncrono
<form id="form-valoracion-ruta">{ % csrf_token %}
<input type="hidden" name="id_ruta" value={{ruta.id}} /> <table>
{{ form.as_table }}
Cap´ıtulo 9. Quinta iteraci ´on
<input type="submit" value="Valorar"><br/> </form>
<script type="text/javascript">
$(’#form-valoracion-ruta’).submit(function(event){ event.preventDefault(); $.ajax({ data: $(this).serialize(), type: ’POST’, url: ’/addValoracion/’, success: function(data){ $(’body’).html(data); }, error: function(){
alert("Error");
}
})
});
</script>
\label{add_valoraciones}
◦ Del resto de tareas as´ıncronas implementadas no se va a comentar el c ´odigo, pues esto supondr´ıa repetir los dos puntos anteriores. S´ı que se procede a enu-merarlas:
• Seguimiento de rutas.
• Cancelaci ´on del seguimiento de rutas.
• Borrado de valoraciones de rutas.
• B ´usqueda de lugares de inter ´es en la p ´agina de d´ıas.
• A ˜nadido de lugares de inter ´es a d´ıas.
• Borrado de lugares de inter ´es en d´ıas.
• Seguimiento de usuarios.
• Cancelaci ´on del seguimiento de usuarios.
• A ˜nadido de valoraciones a lugares de inter ´es.
9.2. Desarrollo
API deGoogle Maps
Para mejorar la experiencia del usuario, se muestran mapas indicando d ´onde se en-cuentran los lugares de inter ´es de las rutas. Para ello se ha hecho uso de la API de
Google Maps, que ofrece diferentes funcionalidades. En este caso se utilizar ´a la geo-localizaci ´on dada una direcci ´on.
Dependiendo de si se desea mostrar un ´unico marcador (como es el caso de la p ´agi-na de informaci ´on de los lugares de inter ´es) o m ´ultiples marcadores (como es el caso de la p ´agina de informaci ´on de d´ıa o ruta), la implementaci ´on de la funci ´on initMap()
(funci ´on encargada de mostrar el mapa con los marcadores) ser ´a diferente.
En el caso de querer mostrar un ´unico marcador, la funci ´oninitMap()crear ´a un nuevo objeto de tipo Map en el que se indicar ´a el estilo del mapa y otro de tipo Geocoder, al que se le indicar ´a la direcci ´on en la que se desea poner el marcador. Tambi ´en se llamar ´a a una funci ´on que ser ´a la encargada de localizar el marcador en la direcci ´on indicada y centrar ´a el mapa en funci ´on del marcador.
En el caso de querer mostrar m ´as marcadores, el desarrollo se complica. En la funci ´on
initMap() ´unicamente se inicializan las variables globales. Tambi ´en se implementa una funci ´ongeocodeAddress(address, next) que geolocaliza la direcci ´on y llama a la fun-ci ´oncreateMarker(add, lat, lng), que ser ´a la encargada de a ˜nadir el marcador al mapa.
Internacionalizaci ´on
La internacionalizaci ´on se ha llevado a cabo tanto en lostemplatescomo en el fichero
forms.py, aunque de maneras diferentes.
Enforms.py se utiliza la funci ´on ()para indicar las cadenas que son traducibles, mien-tras que en los templates es necesario incluir {% load i18n %} antes de la etiqueta <html>. En los templates las cadenas que son traducibles se indican de la siguiente manera:
{% trans “Cadena” %}
do-Cap´ıtulo 9. Quinta iteraci ´on
CAP´ITULO
10
Sexta iteraci ´
on
10.1.
Modificaciones
Este iteraci ´on iteraci ´on ha consistido en arreglar fallos menores, hacer la interfaz m ´as intuitiva y a ˜nadir untimelinea la p ´agina principal de la aplicaci ´on.
La implementaci ´on deltimelinecorresponde a la implementaci ´on del requisito Monito-rizaci ´on de acciones.
10.2.
Desarrollo
10.2.1.
Modelos
Para esta iteraci ´on se ha modificado el archivomodels.py. En ´el se ha implementado una caseLog que almacenar ´a los cambios que hace un usuario en una ruta.
10.2. Desarrollo
10.2.2.
Vistas
En la vistainicio(request) en el archivo views usuario.py se cargan todos los objetos de la claseLog cuyo usuario est ´e en la lista de seguidos del usuario que tiene iniciada la sesi ´on, o cuya ruta est ´e en la lista de rutas seguidas del usuario que tiene iniciada la sesi ´on.
En las vistascrearRuta(request)yeditarRuta(request, id ruta)en el ficheroviews ruta.py
y en las vistasanadirDia(request, id ruta),borrarDia(request, id dia)yeditarDia(request, id dia)en el ficheroviews dia.py se observa un fragmento de c ´odigo com ´un:
C ´odigo 10.1:Log de operaciones
log = models.Log(usuario=usuario,
ruta=ruta,
fecha=timezone.now(),
log=’accion realizada por el usuario’)
log.save()
En ´el se guardan los cambios que ha realizado el usuario para posteriormente mos-trarlos en elTimeline.
En el campologse almacena la acci ´on que realizada, ya sea creaci ´on o modificaci ´on.
10.2.3.
Templates
En esta iteraci ´on los cambios realizados en los ficheros .html son principalmente est ´eticos:
◦ Los enlaces que antes hab´ıa en elNavbar ahora est ´an contenidos dentro de un
Dropdown que se encuentra en elNavbar.
◦ En el Dropdown se han a ˜nadido enlaces a la p ´agina de creaci ´on de ruta, lugar de inter ´es, perfil de usuario, edici ´on del perfil ylog out.
◦ El Navbar pasa a estar fijo en la parte superior de la p ´agina, de manera que el usuario siempre lo tiene a la vista.
Cap´ıtulo 10. Sexta iteraci ´on
◦ La p ´agina principal ahora muestra un panel con las rutas creadas por el usuario y las rutas que sigue y tambi ´en elTimelinecomentado anteriormente.
CAP´ITULO
11
Conclusiones
11.1.
Opini ´
on sobre la uni ´
on de
Django
y
Amazon Web
Services
Para poner en contexto a futuros lectores de este proyecto, mi intenci ´on a la hora de desarrollar esta aplicaci ´on era utilizarJava Server Faces, pero debido a la poca infor-maci ´on que encontr ´e en Internet de aplicaciones Web desarrolladas en Java Server Faces y desplegadas enAmazon Web Services, decid´ı aventurarme a utilizar Django
(a pesar de que no ten´ıa conocimientos de Python) para el mismo pues, tras varios d´ıas investigando, me dio la sensaci ´on de que hab´ıa una gran cantidad de informaci ´on respecto al tema y no perder´ıa mucho tiempo investigando sobre c ´omo desplegar la aplicaci ´on.
11.2. An ´alisis de resultados
A pesar de esto, Django presenta tambi ´en inconvenientes, sobre todo a la hora de desplegar una aplicaci ´on en un servidor. Como se ha comentado en el p ´arrafo an-terior, Django facilita al programador las conexiones con las bases de datos locales, pero, por el contrario, conectarDjangoa una base de datos remota requiere de mucho tiempo y paciencia.
11.2.
An ´alisis de resultados
En el anteproyecto se propuso el desarrollo de una aplicaci ´onWeb utilizando elcloud
de Amazon. Si bien se ha desarrollado la aplicaci ´on web al completo, no me ha sido posible desplegarla en Amazon Web Services, pues la documentaci ´on disponible en
Internet era escasa o estaba desfasada.
Tambi ´en se propuso la entrega de un manual de usuario, este se puede encontrar en elAnexo C.
Ser´ıa interesante hablar tambi ´en de las estimaciones que se hicieron en el antepro-yecto. Si bien se hizo la estimaci ´on del cuadro 11.1, la realidad se aleja bastante de la misma, quedando el tiempo empleado como se refleja en el cuadro 11.2.
Fase Horas
An ´alisis de requisitos 10 An ´alisis de requisitos 51
Dise ˜no 51
Implementaci ´on 52
Pruebas 51
Integraci ´on 51
Memoria 30
Cuadro 11.1: Estimaciones hechas en el anteproyecto