-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpractica-final-2020-05.tex
571 lines (384 loc) · 55 KB
/
practica-final-2020-05.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
%%----------------------------------------------------------------------------
%%----------------------------------------------------------------------------
\section{Proyecto final: MisCosas (2020, mayo)}
\label{practica-final-2020-05}
%[ \textbf{Nota importante:} Por ahora esto es sólo es un borrador. Aún estamos definiendo cómo será el enunciado definitivo. ]
%[ \textbf{Nota importante:} Este enunciado es aún tentativo, y puede sufrir cambios ]
La práctica final de la asignatura consiste en la creación de una aplicación web, llamada ``MisCosas'', que permitirá gestionar vídeos, noticias y otra información que los usuarios vayan encontrando por la red y les resulte interesante. Los usuarios podrán ver los contenidos de sitios preseleccionados, añadir otros, elegir los que más les interesen, y compartir los que han seleccionado de distintas maneras. A continuación se describe el funcionamiento y la arquitectura general de la aplicación, la funcionalidad mínima que debe proporcionar, y otra funcionalidad optativa que podrá tener.
Por un lado, la aplicación se encargará de descargar información de varios sitios de Internet para permitir a los usuarios que puedan elegirla. Por otro, permitirá a los usuarios elegir, entre ellos, qué información quieren que se les muestre para realizar su selección, y podrán compartir estas selecciones con otros usuarios.
%%----------------------------------------------------------------------------
\subsection{Arquitectura y funcionamiento general}
Arquitectura general:
\begin{itemize}
\item La práctica se construirá como un proyecto Django/Python3, que incluirá una o varias aplicaciones (apps) Django que implementen la funcionalidad requerida.
\item Para el almacenamiento de datos persistente se usará SQLite3, con tablas definidas en modelos de Django.
\item Para implementar usuarios, cuando sea necesario, se usará como base el sistema de autenticación de usuarios que proporciona Django\footnote{User Authentication in Django:\\ \url{https://docs.djangoproject.com/en/3.0/topics/auth/}}.
\item Todas las bases de datos que contenga la aplicación tendrán que ser accesibles vía la interfaz que proporciona el ``Admin Site'' (además de lo que pueda hacer falta para que funcione al aplicación).
\item Se utilizarán plantillas Django (a ser posible, una jerarquía de plantillas, para que la práctica tenga un aspecto similar) para definir las páginas que se servirán a los navegadores de los usuarios. Estas plantillas incluirán en todas las páginas al menos:
\begin{itemize}
\item Un \emph{banner} (imagen) del sitio, preferentemente en la parte superior izquierda.
\item Una caja para entrar (hacer login en el sitio), o para salir (si ya se ha entrado).
\begin{itemize}
\item En caso de que no se haya entrado en una cuenta, esta caja permitirá al visitante introducir su identificador de usuario y su contraseña, o crearse una cuenta.
\item En caso de que ya se haya entrado, esta caja mostrará el identificador del usuario y permitirá salir de la cuenta (logout). Esta caja aparecerá preferentemente en la parte superior derecha.
\end{itemize}
\item Un menú de opciones, como barra, preferentemente debajo de los dos elementos anteriores (banner y caja de entrada o salida).
\item Un pie de página con una nota de atribución, indicando ``Esta aplicación utiliza datos proporcionados por XXX, YYY y ZZZ'', siendo XXX, YYY y ZZZ los sitios desde donde se descarga información, y siendo cada uno de ellos un enlace al sitio en cuestión.
\end{itemize}
Cada una de estas partes estará construida dentro de un elemento ``div'', marcada con un atributo ``id'' en HTML, para poder ser referenciadas fácilmente en hojas de estilo CSS.
\item Se utilizarán hojas de estilo CSS para determinar la apariencia de la práctica. Estas hojas definirán al menos el color y el tamaño de la letra, y el color de fondo de cada una de las partes (elementos) marcadas con un \emph{id}, tal como se indica en el apartado anterior. Además, elementos que deban tener el mismo aspecto deberían estar en una misma clase, para poder gestionarlo de forma común.
\item Para obtener información de cada sitio de Internet soportado por la aplicación, se utilizará la API de ese sitio, o quizás en algunos casos, ser hará un análisis de las páginas HTML del sitio. En general, la forma de funcionamiento será la siguiente:
\begin{itemize}
\item Llamaremos ``alimentador'' a cada una de las fuentes de datos del sitio. Por ejemplo, en YouTube, cada alimentador será un canal.
\item Llamaremos ``item'' a cada uno de los elementos de un alimentador. Por ejemplo, en YouTube, cada item será un vídeo.
\item Se ofrecerá un elemento HTML que permita al usuario elegir qué alimentador se va a obtener del sitio.
\item La información obtenida de ese alimentador se organizará como una lista de items, que se almacenará en la base de datos.
\item A partir de lo almacenado en la base de datos, se ofrecerá al usuario la lista de items para la selección.
\item Se ofrecerá una forma para actualizar la información.
\end{itemize}
Puede verse más información sobre los alimentadores en la sección~\ref{practica-final-2020-05:alimentadores}.
\end{itemize}
Funcionamiento general:
\begin{itemize}
\item En general, para utilizar el sitio, no hará falta autenticarse con una cuenta. Toda la funcionalidad estará disponible para cualquier visitante, mientras use el sitio desde el mismo navegador y tenga las cookies habilitadas.
\item Cuando un visitante quiera, se podrá abrir una cuenta (y quedará autenticado en ella), o autenticarse en una cuenta ya existente. En este caso, la funcionalidad quedará ligada a su cuenta.
\item Cada usuario podrá elegir cualquier ítem que se le presente, y realizar dos acciones fundamentales con él (comentarlo, y votarlo):
\begin{itemize}
\item Comentar un ítem quiere decir escribir un pequeño mensaje (menos de 256 caracteres) que quedará relacionado con el item.
\item Votarlo significa darle un voto positivo o uno negativo. El resultado de las votaciones quedará relacionado con el ítem.
\end{itemize}
\end{itemize}
%%----------------------------------------------------------------------------
\subsection{Alimentadores}
\label{practica-final-2020-05:alimentadores}
La práctica tendrá que funcionar con al menos dos alimentadores entre los que se describen a continuación. El número 0 (YouTube canal XML) será obligatorio para todos. Además, cada alumno tendrá que implementar al menos otro, según la primera letra de su primer apellido: alimentador 1 para las letras A-D, alimentador 2 para las letras E-L, alimentador 3 para las letras M-Q, alimentador 4 para las letras R-Z.
Alimentadores descritos:
\begin{itemize}
\item \textbf{Alimentador 0}. YouTube (canal XML). En este caso el alimentador será el canal de YouTube, y el item será un vídeo en particular. Los últimos vídeos de un canal están disponibles como documentos XML (RSS)\footnote{Ejemplo: Para el canal \emph{UC300utwSVAYOoRLEqmsprfg}, la url es:\\ \url{https://www.youtube.com/feeds/videos.xml?channel_id=UC300utwSVAYOoRLEqmsprfg}}, donde el identificador del canal se puede obtener del enlace que tenemos en el navegador cuando estamos viendo el canal. Funcionamiento:
\begin{itemize}
\item Alimentador: canal de Youtube.
\item Ítem: vídeo de YouTube.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir el identificador del canal.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con los vídeos disponibles en el canal RSS.
\item Datos mostrados para el alimentador cuando se muestra resumido: nombre (título) del canal, enlace del canal, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: nombre (título) del canal, enlace del canal, y lista de vídeos (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título del vídeo, enlace del vídeo
\item Datos mostrados del ítem (cuando se muestra con detalle): título del vídeo, enlace del vídeo, descripción del vídeo, vídeo empotrado, nombre del canal, enlace del canal.
\end{itemize}
\item \textbf{Alimentador 1}. Reddit (Subreddit). En este caso, el alimentador será un Subreddit (una sección de Reddit, como por ejemplo \verb|r/memes|), y el item una noticia en el Subreddit. Las últmas noticias de un Subreddit están disponibles como documento XML (RSS)\footnote{Ejemplo: Para el Subreddit \emph{memes}, la url es:\\ \url{https://www.reddit.com/r/memes.rss}}. Más información en el wiki de Reddit\footnote{What features does reddit have?: \\ \url{https://www.reddit.com/wiki/rss}}. Funcionamiento:
\begin{itemize}
\item Alimentador: Subreddit (sección) de Reddit.
\item Ítem: noticia del Subreddit.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir el nombre del Subreddit.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con las noticias disponibles en el canal RSS.
\item Datos mostrados para el alimentador cuando se muestra resumido: nombre (título) del Subreddit, enlace del Subreddit, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: nombre (título) del Subreddit, enlace del Subreddit, y lista de noticias (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título de la noticia, enlace de la noticia.
\item Datos mostrados del ítem (cuando se muestra con detalle): título de la noticia, enlace de la noticia, descripción de la noticia, nombre del Subreddit, enlace del Subreddit.
\end{itemize}
\item \textbf{Alimentador 2}. Last.fm (artista). En este caso, el alimentador será un artista de Last.fm (como por ejemplo \verb|Cher|), y el item un álbum. Los álbumes de un artista están están disponibles como documento XML o JSON\footnote{Ejemplo: Para \emph{Cher}, la url es:\\ \url{http://ws.audioscrobbler.com/2.0/?method=artist.gettopalbums&artist=cher&api_key=YOUR_API_KEY}}. Más información en la documentación ``Last.fm Web Services\footnote{Last.fm Web Services, artist.getTopAlbums: \\ \url{https://www.last.fm/api/show/artist.getTopAlbums}}. \textbf{Atención:} Para el uso de este servicio hace falta conseguir una ``clave de API''\footnote{Para conseguir la clave de API en Last.fm (mira también en las preguntas frecuentes): \\\url{https://www.last.fm/api/account/create}}, que tendrás que poner en las llamadas en lugar de \verb|YOUR_API_KEY|. Consulta la lista de preguntas frecuentes (apartado~\ref{sec:practica-2020-05:preguntas}), hay una que trata justamente sobre este tema~(página \pageref{sec:practica-2020-05:preguntas-apikey}).
Funcionamiento:
\begin{itemize}
\item Alimentador: Artista en Last.fm.
\item Ítem: álbum de un artista en Last.fm.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir el nombre del artista.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con los álbumes disponibles para el artista.
\item Datos mostrados para el alimentador cuando se muestra resumido: nombre del artista, enlace al artista, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: nombre del artista, enlace del artista, y lista de álbumes (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título del álbum, enlace del álbum.
\item Datos mostrados del ítem (cuando se muestra con detalle): título del álbum, enlace del álbum, portada del álbum, nombre del artista, enlace del artista.
\end{itemize}
\item \textbf{Alimentador 3}. Flickr (etiqueta). En este caso, el alimentador será una eitqueta (tag) de Flickr (como por ejemplo ``Fuenlabrada''), y el item una foto con esa etiqueta. Las fotos que tienen una etiqueta están disponibles como documento XML\footnote{Ejemplo: Para la etiqueta ``Fuenlabrada'' la url es: \\ \url{https://www.flickr.com/services/feeds/photos_public.gne?tags=fuenlabrada}}. Más información en la página Public Feed de Flickr\footnote{Public Feed de Flickr: \\ \url{https://www.flickr.com/services/feeds/docs/photos_public/}}. Funcionamiento:
\begin{itemize}
\item Alimentador: Etiqueta de Flickr.
\item Ítem: foto de Flickr.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir la etiqueta.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con las fotos de la etiqueta.
\item Datos mostrados para el alimentador cuando se muestra resumido: etiqueta, enlace a las fotos con esa etiqueta en Flickr\footnote{Por ejemplo, para la etiqueta ``Fuenlabrada'', el enlace sería: \\\url{https://www.flickr.com/search/?tags=fuenlabrada}}, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: etiqueta, enlace a la página de la etiqueta en Flickr, y lista de fotos para esa etiqueta (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título de la foto, enlace a la página de la foto en Flickr.
\item Datos mostrados del ítem (cuando se muestra con detalle): título de la foto, enlace a la página de la foto en Flickr, foto, etiqueta, enlace a la página de la etiqueta en Flickr.
\end{itemize}
\item \textbf{Alimentador 4}. Wikipedia (historia de artículos). En este caso, el alimentador será la historia de un artículo de Wikipedia (como por ejemplo ``Madrid''), y el item la descripción de un cambio en esa historia. La historia de un artículo está disponible como documento XML\footnote{Ejemplo: Para la página ``Fuenlabrada'' la url es: \\ \url{https://en.wikipedia.org/w/index.php?title=Fuenlabrada&action=history&feed=rss}}. Más información en la página Wikipedia Syndication\footnote{Wikipedia Syndication: \\ \url{https://en.wikipedia.org/wiki/Wikipedia:Syndication}} (sección ``RSS Feeds''). Funcionamiento:
\begin{itemize}
\item Alimentador: historia de un artículo de Wiipedia.
\item Ítem: cambio en la historia de un artículo.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir el nombre del artículo.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con la historia de un artículo.
\item Datos mostrados para el alimentador cuando se muestra resumido: nombre del artículo, enlace al articulo en la Wikipedia, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: nombre del artículo, enlace al articulo en la Wikipedia, y lista de cambios para ese articulo (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título del cambio, enlace al cambio.
\item Datos mostrados del ítem (cuando se muestra con detalle): título del cambio, enlace al cambio, autor del cambio, fecha del cambio, nombre del artículo, enlace al articulo en la Wikipedia.
\end{itemize}
\end{itemize}
Otros alimentadores, entre ellos algunos sugeridos por alumnos de la asignatura, por si te interesa implementarlos:
\begin{itemize}
\item TodoLiteratura (sección). En este caso, el alimentador será una sección de TodoLiteratura (como por ejemplo ``Actualidad''), y el item un artíclo de la sección. Las noticias de una sección están disponibles como documento XML\footnote{Ejemplo: Para la sección ``Actualidad'' se usa el número ``127'', y la url es: \\ \url{https://www.todoliteratura.es/rss/seccion/127/}}. Más información en la página de canales RSS de TodoLiteratura\footnote{Página de canales RSS de Todo Literatura: \\ \url{https://www.todoliteratura.es/rss/}}. Funcionamiento:
\begin{itemize}
\item Alimentador: Sección en TodoLiteratura.
\item Ítem: noticia en una sección de TodoLiteratura.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir el identificador de la seccion (número de la sección). Alternativamente, se puede usar un menú que de cómo opción varias de las secciones.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con las noticias disponibles en una sección.
\item Datos mostrados para el alimentador cuando se muestra resumido: título de la sección, enlace a la sección, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: título de la noticia, enlace a la sección, descripción de la sección, y lista de noticias (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título de la noticia, enlace a la noticia.
\item Datos mostrados del ítem (cuando se muestra con detalle): título de la noticia, enlace a la noticia, descripción de la noticia, título de la sección, enlace a la sección.
\end{itemize}
\item TuCanaldeSalud (sección). En este caso, el alimentador será una sección de TuCanaldeSalud (como por ejemplo ``Tecnología''), y el item un artíclo de la sección. Las noticias de una sección están disponibles como documento XML\footnote{Ejemplo: Para la sección ``Tecnología'' se usa el número ``70038'', y la url es: \\ \url{https://www.tucanaldesalud.es/idcsalud-client/cm/tucanaldesalud/rss?locale=es_ES&rssContent=70038}}. Más información en la página de canales RSS de TuCanaldeSalud\footnote{Página de canales RSS de TuCanaldeSalud: \\ \url{https://www.tucanaldesalud.es/es/feed-rss}}. Funcionamiento:
\begin{itemize}
\item Alimentador: Sección en TuCanaldeSalud.
\item Ítem: noticia en una sección de TuCanaldeSalud.
\item Elemento HTML para elegir el alimentador: formulario que permita escribir el identificador de la seccion (número de la sección). Alternativamente, se puede usar un menú que de cómo opción varias de las secciones.
\item Elemento HTML para actualizar el alimentador: botón que actualiza con las noticias disponibles en una sección.
\item Datos mostrados para el alimentador cuando se muestra resumido: título de la sección, enlace a la sección, total de items disponibles para este alimentador, puntuación (total de votos positivos menos votos negativos para todos sus items).
\item Datos mostrados para el alimentador cuando se muestra con detalle: título de la noticia, enlace a la sección, descripción de la sección, y lista de noticias (con información resumida).
\item Datos mostrados del ítem (cuando se muestra resumido): título de la noticia, enlace a la noticia.
\item Datos mostrados del ítem (cuando se muestra con detalle): título de la noticia, enlace a la noticia, descripción de la noticia.
\end{itemize}
\end{itemize}
Además de las anteriores, puedes proponer otros alimentadores. Los requisitos fundamentales son que sean accesibles públicamente (el acceso mediante un token de aplicación se considera público), y que proporcionen datos en formato XML o JSON. Si hay algún alimentador que querrías utilizar, coméntalo con los profesores para que te indiquen si es un alimentador válido. En caso de ser aceptado como válido, estos alimentadores serán puntuados positivamente, teniendo en cuenta la iniciativa del alumno que los propuso.
Si quieres buscar servicios que ofrezcan APIs que podrían ser alimentadores, puedes buscarlos en Internet. Una lista por la que puedes comenzar es la que mantiene ProgrammableWeb\footnote{Programmable Web API Directory: \\\url{https://www.programmableweb.com/apis/directory}}.
%%----------------------------------------------------------------------------
\subsection{Funcionalidad mínima}
La aplicación servirá las siguientes páginas:
\begin{itemize}
\item Página principal de la aplicación:
\begin{enumerate}
\item Listado con los 10 items (formato resumido) que han conseguido más puntuación (votos positivos menos votos negativos) en el sitio. Para cada uno se mostrarán sus votos positivos y negativos, y un enlace a la página del item (ver a continuación).
\item Formulario para elegir alimentador, para cada uno de los sistemas de alimentación (por ejemplo, canales de YouTube) disponibles. Tras elegir un alimentador vía el formulario, se recibirá la página del alimentador elegido (ver a continuación), con información actualizada, y se almacenarán sus datos en la base de datos (todos los recibidos, si es la primera vez que se le ha elegido, o lo que no estuvieran ya en la base de datos, si ya se hubiera elegido anteriormente).
\item Listado de alimentadores elegidos en el pasado (formato resumido), por cualquier usuario. Cada alimentador aparecerá con un botón para poder elegirlo (si se elige de esta forma, la aplicación se comportará igual que si se hubiera elegido vía el formulario), y otro para eliminarlo (si se pulsa, el alimentador dejará de salir en este listado en el futuro). Cualquier visitante o usuario podrá eliminar un canal de este listado, pero eso no supondrá que sus datos desaparezcan de la base de datos, y en cualquier caso el alimentador seguirá saliendo en la página de alimentadores.
\end{enumerate}
Si el visitante está además autenticado como usuario, se mostrará también:
\begin{itemize}
\item Listado con los últimos 5 items (formato resumido) votados por el usuario (tanto positiva como negativamente).
\item Para cada item que aparezca en la página se mostrarán también dos botones para votar (positivo, negativo), resaltando de alguna forma que el valor que se haya votado, si se hubiera votado ya ese item, y un enlace a la página del item (ver a continuación).
\end{itemize}
\item Página del ítem (para cada ítem):
\begin{itemize}
\item Datos del ítem (formato detallado).
\item Datos del alimentador al que pertenece el ítem (formato resumido), incluyendo un enlace a la página del alimentador.
\item Comentarios que haya recibido el ítem. Para cada comentario se mostrará el texto del comentario, el identificador de quien lo puso, y la fecha en que se puso.
\end{itemize}
Si el visitante está además autenticado como usuario, se mostrará también:
\begin{itemize}
\item Dos botones para votar (positivo, negativo), resaltando de alguna forma que el valor que se haya votado, si se hubiera votado ya ese item.
\item Formulario para poner un comentario. Tras poner el comentario, se volverá a ver la misma página del ítem.
\end{itemize}
\item Página de alimentadores:
\begin{itemize}
\item Listado de todos los alimentadores de los que se ha podido descargar datos alguna vez (formato resumido). Esto es, todos los que se han ``seleccionado'' alguna vez, por cualquier visitante, aunque no salgan en la página principal.
\end{itemize}
\item Página de alimentador (para cada alimentador):
\begin{itemize}
\item Datos del alimentador (formato detallado)
\item Botón para poder elegir o dejar de tener elegido el alimentador. Si se pulsa, y no estaba elegido, el alimentador pasará a estar elegido, con los mismos efectos que si se hubiera elegido en el formulario de la página principal. Si se pulsa, y estaba elegido, pasa a dejar de estar elegido, con el mismo efecto que se hubiera pulsado el botón de ``eliminar'' del listado de alimentadores elegidos de la pagina principal. El botón tendrá que indicar de alguna manera (por ejemplo, con dos textos distintos, o con colores distintos) si el alimentador está o no elegido, antes de pulsarlo. En ningún caso si un alimentador pasa a dejar de estar elegido, se eliminarán sus datos de la base de datos: sólo dejará de salir en el listado de elegidos.
\item Lista de items del alimentador (formato resumido).
\item Para cada ítem, enlace a la página del ítem.
\end{itemize}
\item Página de usuario (para cada usuario ``con cuenta''). Página ``pública'', que verá cualquiera que cargue el recurso apropiado:
\begin{itemize}
\item Datos públicos del usuario (identificador, foto)
\item Lista de items votados por ese usuario (formato resumido)
\item Lista de items comentados por ese usuario (formato resumido)
\end{itemize}
Si el visitante está autenticado, cuando acceda a su propia página, se mostrará también:
\begin{itemize}
\item Formulario para cambiar la foto
\item Formulario para cambiar de estilo. Se ofrecerán al menos dos estilos: ``ligero'' y ``oscuro''.
\item Formulario para cambiar el tamaño de la letra. Se ofrecerán al menos tres tamaños: ``pequeña'', ``normal'' y ``grande''.
\end{itemize}
\item Página de usuarios:
\begin{itemize}
\item Listado de todos los usuarios ``con cuenta''. Para cada usuario, aparecerá su identificador, su foto, el número de items votados, el número de comentarios que ha hecho, y un enlace a su página de usuario.
\end{itemize}
La página principal se ofrecerá también como un documento XML y como un documento JSON, que incluiría la misma información (los mismos listados de items y alimentadores). Este documento se ofrecerá cuando se pida la página principal, concatenando al final \verb|?format=xml| o \verb|?format=json|.
La página principal en formato HTML incluirá un enlace a la página principal en formato XML (``Descarga como fichero XML'') y JSON (``Descarga como fichero JSON'').
\item Página de información: Página con información en HTML indicando la autoría de la práctica, explicando su funcionamiento y una brevísima documentación.
\end{itemize}
La aplicación se encargará de controlar que no haya más de un voto (positivo o negativo) por usuario para cada ítem. Por lo tanto, si un usuario ya ha votado un ítem, y vuele a votarlo, se ignorará su voto (si es igual que el que está almacenado) o se anotará el nuevo (si es distinto). Por ejemplo, si había votado un ítem con positivo, y ahora vuelve a votarlo con positivo, se ignorará el segundo voto. Si vuelve a votarlo, pero ahora con negativo, se cambiará el voto a negativo.
En todos los casos en que se vote, tras votar se volverá a ver la misma página en que se estaba, ahora con el voto contabilizado.
Todas las páginas un menú desde el que se podrá acceder a la página principal (con el texto ``Inicio''), a la de alimentadores (con el texto ``Alimentadores''), a la de usuarios (con el texto ``Usuarios'') y a la de información (con el texto ``Información''), salvo que ya estés en esa página, en cuyo caso no saldrá el elemento de menú correspondiente.
Además, la práctica incluirá tests, que se ejecutarán con \verb|python3 manage.py test|, y que incluirán al menos un test de API HTTP para cada recurso que sirva la aplicación, y para cada método (GET, POST) que admita cada recurso. Además, al menos la mitad de los test incluirán comprobar algo distinto del código HTTP retornado por la petición.
%%----------------------------------------------------------------------------
\subsection{Despliegue}
\label{sec:practica-2020-05:despliegue}
La práctica deberá estar desplegada en algún sitio de Internet, de forma que pueda accederse a ella. Deberá mantenerse desplegada y activa al menos desde el día de entrega de la práctica, hasta el día del cierre de actas.
Para el despliegue, se puede utilizar Python Anywhere\footnote{Python Anywhere: \url{https://pythonanywhere.com}}, que proporciona un plan gratuito que incluye suficientes recursos como para poder desplegar la práctica.
Si el alumno así lo desea, puede considerarse desplegar en un ordenador dedicado (por ejemplo, una Raspberry Pi accesible directamente desde Internet, alojada en su hogar), o en servicios como Google Computing Engine\footnote{GCP Engine Free: \url{https://cloud.google.com/free/}}. En general, dado que este tipo de despliegues no podrá contar con una ayuda detallada por los profesores, estará algo más valorado.
En el caso de que la práctica se despliegue en Python Anywhere, hay que tener en cuenta que sus máquinas virtuales tienen cortado el acceso a todos los sitios de Internet salvo los que están en una ``lista blanca''\footnote{Lista blanca de Python Anywhere: \url{https://www.pythonanywhere.com/whitelist/}} (\emph{whitelist}). Esto afectará a vuestro despliegue de dos formas:
\begin{itemize}
\item Al clonar vuestro repositorio git dentro de la máquina virtual, para tener el código de vuestra aplicación. No debería dar problemas, porque el sitio GitLab de la ETSIT, donde está vuestro código fuente, está ya en la lista blanca.
\item Cuando vuestra aplicación se conecte para actualizar un alimentador. Si el sitio al que la aplicación se tiene que conectar para conseguir el documento JSON o XML no está en la lista blanca, vuestra aplicación no se podrá conectar. YouTube (que está en la parte obligatoria para todo el mundo) y algunos otros sitios de alimentadores (como Flickr) están ya en la lista blanca. Pero otros sitios que podéis estar usando, no.
\end{itemize}
Para evitar los problemas con los sitios que no estén en la lista blanca, os pedimos que si hacéis el despliegue en YouTube:
\begin{itemize}
\item La actualización (``selección'') de alimentadores tiene que funcionar al menos con YouTube, recogiendo los documentos XML correspondientes, como indica el enunciado.
\item Para los demás alimentadores que hayáis implementado, tenéis dos opciones:
\begin{itemize}
\item Si están en la lista blanca de Python Anywhere, funcionarán sin problemas sin hacer nada especial, si os funcionaban ya en las pruebas locales, así que también deberían funcionar en el despliegue.
\item Si no están en la lista blanca de Python Anywhere, aseguraos de que la base de datos que subís al despliegue de vuestra práctica incluya datos de alimentadores de la plataforma en cuestión. Por ejemplo, si tenéis implementados alimentadores de Last.fm, basta con que tengáis en la base de datos items de un par de artistas, que muestren que en la versión local os funcionó.
\end{itemize}
\end{itemize}
Tened en cuenta que si usáis otras plataformas para el despliegue, puede que os encontréis problemas similares. Y tened en cuenta también que en cualquier caso, nosotros probaremos la práctica en otros despliegues, así que todos los alimentadores que hayáis implementado deben funcionar correctamente si no hay restricciones de conexión.
%%----------------------------------------------------------------------------
\subsection{Funcionalidad optativa}
De forma optativa, se podrá incluir cualquier funcionalidad relevante en el contexto de la asignatura. Se valorarán especialmente las funcionalidades que impliquen el uso de técnicas nuevas, o de aspectos de Django no utilizados en los ejercicios previos, y que tengan sentido en el contexto de esta práctica y de la asignatura.
En el formulario de entrega se pide que se justifique por qué se considera funcionalidad optativa lo que habéis implementado. Sólo a modo de sugerencia, se incluyen algunas posibles funcionalidades optativas:
\begin{itemize}
\item Inclusión de un \emph{favicon} del sitio
\item Visualización de cualquier página en formato JSON y/o XML, de forma similar a como se ha indicado para la página principal.
\item Generación de un canal RSS, XML libre y/o JSON para los comentarios puestos en el sitio.
\item Incorporación de datos de otros alimentadores además de los obligatorios. Se valorará especialmente la búsqueda de otros alimentadores no descritos en este enunciado, la implementación de alimentadores no basados en RSS (o derivados), y la implementación de alimentadores que requieran de token de autenticación (en este caso, atención a no subir el token de autenticación a GitLab).
\item Atención al idioma indicado por el navegador. El idioma de la interfaz de usuario de la aplicación tendrá en cuenta lo que especifique el navegador.
\item Utilización de Bootstrap\footnote{Bootstrap: \url{https://getbootstrap.com/}} para la maquetación del sitio web.
\item Inclusión de imágenes (no solo texto) en los comentarios. Esto puede hacerse de dos formas: quien suba un comentario, además de rellenar una caja de texto con el comentario, puede indicar también la url de una imagen, que se mostrará junto al comentario, o bien subiendo una imgen a la aplicación, que se mostrará junto al comentario (se valorará más la segunda opción, y se pueden implementar las dos).
\item Mejora de los tests de la práctica, incluyendo test de condiciones de error, test de escenarios con más de una invocación de recurso, tests de API Python, etc.
\end{itemize}
%%----------------------------------------------------------------------------
\subsection{Entrega de la práctica}
\begin{itemize}
\item \textbf{Fecha límite de entrega de la prueba teórica:} viernes, 12 de junio de 2020 a las 15:00 (hora española peninsular)
%{\bf Convocatoria de junio:} miércoles, 24 de junio de 2015 a las 23:59 (hora peninsular española).
\item \textbf{Fecha límite de entrega de la práctica:} domingo, 14 de junio de 2020 a las 23:59 (hora española peninsular)
\item \textbf{Notificación de alumnos que tendrán que realizar entrevista:} martes, 16 de junio, en el aula virtual.
%{\bf Convocatoria de junio:} viernes, 26 de junio, en la plataforma Moodle.
\item \textbf{Realización de entrevistas:} miércoles, 17 de junio, en la aplicación Teams. Si es necesario, se realizarán también los días 18 y 19.
\item \textbf{Fecha de publicación de notas:} viernes, 19 de junio, en el aula virtual.
%{\bf Convocatoria de junio:} viernes, 26 de junio, en la plataforma Moodle.
\item \textbf{Fecha de revisión:} lunes, 22 de junio, a las 12:00, en la aplicación Teams.
%{\bf Convocatoria de junio:} martes, 30 de junio a las 13:30. Se requerirá a algunos alumnos que asistan a la revisión {\bf en persona}; se informará de ello en el mensaje de publicación de notas.
\end{itemize}
La entrega de la práctica consiste en:
\begin{enumerate}
\item {\bf Rellenar un formulario} enlazado en el sitio de la asignatura en el aula virtual.
\item {\bf Subir tu práctica a un repositorio en el GitLab de la Escuela}. El repositorio contendrá todos los ficheros necesarios para que funcione la aplicación (ver detalle más abajo). Es muy importante que el alumno haya realizado una derivación (fork) del repositorio que se indica a continuación, porque si no, la práctica no podrá ser identificada:
\url{https://gitlab.etsit.urjc.es/cursosweb/practicas/server/final-miscosas/}
Recordad que es importante ir haciendo commits de vez en cuando y que sólo al hacer push estos commits son públicos. Antes de entregar la práctica, haced un push. Y cuando la entreguéis y sepáis el nombre del repositorio, podéis cambiar el nombre del repositorio desde el interfaz web de GitLab.
Se recomeinda mantener el repositorio como privado, hasta el momento en que se entregue la práctica.
\item {\bf Entregar un vídeo de demostración de la parte obligatoria, y otro vídeo de demostración de la parte opcional}, si se han realizado opciones avanzadas. Los vídeos serán de una {\bf duración máxima de 3 minutos} (cada uno), y consistirán en una captura de pantalla de un navegador web utilizando la aplicación, y mostrando lo mejor posible la funcionalidad correspondiente (básica u opcional). Siempre que sea posible, el alumno comentará en el audio del vídeo lo que vaya ocurriendo en la captura. Los vídeos se colocarán en algún servicio de subida de vídeos en Internet (por ejemplo, Vimeo, Twitch, o YouTube). Los vídeos de más de tres minutos tendrán penalización.
Hay muchas herramientas que permiten realizar la captura de pantalla. Por ejemplo, en GNU/Linux puede usarse Gtk-RecordMyDesktop o Istanbul (ambas disponibles en Ubuntu). OBS Studio\footnote{OBS Studio: \url{https://obsproject.com/}} está disponible para varias plataformas (Linux, Windows, MacOS). Es importante que la captura sea realizada de forma que se distinga razonablemente lo que se grabe en el vídeo.
En caso de que convenga editar el vídeo resultante (por ejemplo, para eliminar tiempos de espera) puede usarse un editor de vídeo, pero siempre deberá ser indicado que se ha hecho tal cosa con un comentario en el audio, o un texto en el vídeo. Hay muchas herramientas que permiten realizar esta edición. Por ejemplo, en GNU/Linux puede usarse OpenShot o PiTiVi.
\end{enumerate}
Sobre la entrega del repositorio:
\begin{itemize}
\item Se han de entregar los siguientes ficheros:
\begin{itemize}
\item El repositorio en la instancia GitLab de la ETSIT deberá contener un proyecto Django completo y listo para funcionar en el entorno del laboratorio, incluyendo la base de datos. Deberá poder ejecutarse directamente con \verb|python3 manage.py runserver| desde un entorno virtual en el que esté instalado Django~3.0.3. Tmbién ejecutará los tests con \verb|python3 manage.py test|, desde el mismo entorno virtual.
\item La base de datos habrá de tener datos suficientes como para poder probarlo. Estos datos incluirán al menos dos usuarios con sus datos correspondientes, con al menos cinco alimentadores elegidos en total, cinco comentarios puestos en total, y al menos 10 items votados por cada usuario.
\item Un fichero \verb|requirements.txt|, con un nombre de paquete Python por línea, para indicar Cualquier biblioteca Python que pueda hacer falta para que la aplicación funcione, si es que fuera el caso. Este fichero no ha de incluir Django, dado que ya se supone que hace falta. Si es posible, se recomienda escribir este fichero en el formato que entiende \verb|pip install -r requirements.txt|
\item Cualquier fichero auxiliar que pueda hacer falta para que funcione la práctica, si es que fuera el caso.
\end{itemize}
\item Se incluirán en el fichero README.md los siguientes datos (la mayoría de estos datos se piden también en el formulario que se ha de rellenar para entregar la práctica: se recomienda hacer un copia y pega de estos datos en el formulario):
\begin{itemize}
\item Nombre y titulación.
\item Nombre de su cuenta en el laboratorio del alumno.
\item URL del vídeo demostración de la funcionalidad básica
\item URL del vídeo demostración de la funcionalidad optativa, si se ha realizado funcionalidad optativa
\item URL de la aplicación desplegada
\item Cuenta (login) y contraseña de los usuarios que están dados de alta en la aplicación.
\item Resumen de las peculiaridades que se quieran mencionar sobre lo implementado en la parte obligatoria.
\item Lista de funcionalidades opcionales que se hayan implementado, y breve descripción de cada una.
\end{itemize}
Estos datos se escribirán siguiendo estrictamente el siguiente formato:
\begin{verbatim}
# Entrega practica
## Datos
* Nombre:
* Titulación:
* Despliegue (url):
* Video básico (url):
* Video parte opcional (url):
* Despliegue (url):
*
## Cuenta Admin Site
* usuario/contraseña
## Cuentas usuarios
* usuario/contraseña
* usuario/contraseña
* ...
## Resumen parte obligatoria
## Lista partes opcionales
* Nombre parte:
* Nombre parte:
* ...
\end{verbatim}
Asegúrate de que las URLs incluidas en este fichero están adecuadamente escritas en Markdown, de forma que la versión HTML que genera GitLab los incluya como enlaces ``pinchables''.
\end{itemize}
%%----------------------------------------------------------------------------
\subsection{Notas y comentarios}
La práctica deberá funcionar en el entorno GNU/Linux (Ubuntu) del laboratorio de la asignatura con la versión de Django que se ha usado en prácticas.
La práctica deberá funcionar desde el navegador Firefox disponible en el laboratorio de la asignatura.
Los canales (feeds) RSS que produce la aplicación web realizada en la práctica deberán funcionar al menos con el navegador Firefox (considerándolos como canales RSS) disponibles en el laboratorio. Los documentos XML deberán ser correctos desde el punto de vista de la sintaxis XML, y por lo tanto reconocibles por un reconocedor XML, como por ejemplo el del módulo xml.sax de Python. Los documentos JSON generados deberán ser correctos desde el punto de vista de la sintaxis JSON, y por lo tanto reconocibles por un reconocedor JSON, como por ejemplo el del módulo json de Python
%%----------------------------------------------------------------------------
\subsection{Preguntas frecuentes}
\label{sec:practica-2020-05:preguntas}
A continuación, algunas preguntas relacionadas con el enunciado de esta práctica, junto con sus respuestas:
\begin{itemize}
\item Cuando despliego mi práctica en Python Anywhere, algunos alimentadores no me funcionan, pero otros (YouTube entre ellos), sí. Todo me funciona bien en mi versión local. ¿Qué está pasando?
Las máquinas virtuales de Python Anywhere están limitadas en cuanto a los sitios a los que se pueden conectar: sólo se pueden conectar a aquellos que están en una cierta ``lista blanca''. Por eso, si el sitio al que tu programa se tiene que conectar para obtener items de un alimentador no está en la lista blanca, no va a poder descargarse el documento XML o JSON con esos items. Para evitar problemas, en el caso de despliegue en Python Anywhere pedimos que funcionen bien los alimentadores que están en la lista blanca, y para los demás, que tengan items en la base de datos de despliegue. Más detalles en el apartado sobre despliegue de este enunciado (\ref{sec:practica-2020-05:despliegue}).
\item En la pagina de información que se menciona en el enunciado, ¿qué hay que incluir en el apartado de documentación?
Casi que lo que queráis, lo importante es tener la página. Puede ser por ejemplo un resumen de un párrafo de lo que hace la aplicación.
\item ¿Qué es la ``API key'' en los alimentadores de Last.fm, y en otros alimentadores?
\label{sec:practica-2020-05:preguntas-apikey}
Algunas API de servicio, entre ellas la de Last.fm, requieren el uso de una ``API key'' (clave de API) para poder usarla. Normalmente, estas claves las usa el servicio para evitar abusos, o para limitar lo que se puede hacer con su API. El caso es que si no se incluye la clave de API en cada GET que se hace al servicio, no se reciben los datos (el documento XML o JSON).
Es habitual que estas claves se obtengan creándose una cuenta en el servicio en cuestión, y luego obteniendo la clave en una página al efecto, estando autenticados con el servicio.
Por ejemplo, en el caso de Last.fm, hay que ir a la página de petición de claves de API\footnote{Lastfm Create API Account: \url{https://www.last.fm/api/account/create}}, donde (una vez autenticados con una cuenta de Last.fm), rellenaremos los dato que nos pide: ``contact email'', ``aplication name'' (cualquier nombre de aplicación, por ejemplo MisCosas), ``appication description'' (cualquier descripción por ejemplo ``App to manage Last.fm artists''). En este caso, puedes ignorar los campos ``callback url'' y ``application homepage''. Cuando se hayan enviado estos datos, te devolverá entre otros datos tu ``API key''. Esa es la que tendrá que usar en tus llamadas a Last.fm.
Como las claves de API son personales, mantenlas en secreto. En particular, no las subas a repositorios públicos, pues cualquiera podrá verlas (y usarlas). Si quieres que el repositorio de tu práctica sea público, incluye la clave en un fichero que tengas sólo en tu disco, y no subas al repositorio git. Por ejemplo, puedes poner la clave en un fichero \verb|apikeys.py| del estilo de este:
\begin{verbatim}
LASTFM_APIKEY = "012345678"
\end{verbatim}
Luego, en el módulo Python que la uses (por ejemplo \verb|views.py|), pondrás algo como:
\begin{verbatim}
from .apikeys import LASTFM_APIKEY
\end{verbatim}
Y ya puedes usar la clave en tu código. Este fichero \verb|apikeys.py| no lo subirás al repositorio git público.
Si usas claves de API en tu práctica, indícalo claramente en el fichero de entrega de la práctica, y o bien sube una clave de API válida (si el repositorio de entrega es privado) para que la podamos probar, o bien indica en qué fichero hay que ponerla, y cómo se consigue una clave API válida para el servicio que estés usando, de forma que la podamos conseguir y ejecutar tu práctica.
\item ¿Qué tiene que haber en la página de usuarios?
En el enunciado tenemos una página de usuarios, con un listado de todos los usuarios (visitantes con cuenta). En la primera versión de este enunciado, se incluía, para cada usuario en este listado, un ``número de alimentadores que ha elegido''. Pero al simplificar el enunciado para que la lista de seleccionados sea común a todo el sitio, y no particular a un visitante, esto ya no tiene sentido. Así que lo hemos sustituido por un ``número de comentarios que ha hecho'' (el usuario). Por lo tanto, el enunciado actual indica que esta página mostrará:
\begin{quote}
{\em Listado de todos los usuarios ``con cuenta''. Para cada usuario, aparecerá su identificador, su foto, el número de items votados, el número de comentarios que ha hecho, y un enlace a su página de usuario.}
\end{quote}
\item ¿Qué tiene que haber en la página de alimentadores?
En esta página tiene que esta la lista de alimentadores que se han elegido alguna vez, aunque luego se hayan ``deseleccionado''. Esto es, será la lista de todos los alimentadores que tenemos en la base de datos.
\item ¿Qué alimentadores tienen que tener una página de alimentador?
Todos los alimentadores que se hayan elegido alguna vez tienen que tener pagina de alimentador, aunque luego se hayan ``deseleccionado''. Esto es, todos los alimentadores que tenemos en la base de datos tienen que tener página de alimentador.
\item ¿Cómo se comporta el botón que tengo en la página de un alimentador?
En la página de alimentadot hay un botón ``para poder elegir o dejar de tener elegido el alimentador''. Este botón se muestra siempre, esté el visitante autenticado o no. Si el alimentador no ha sido ``deselegido'' nunca, al pulsar el botón se ``deselegirá'', con el efecto que dejará de salir en el listado de alimentadores elegidos (en la página principal). Pero no será borrado de la base de datos, seguirá saliendo en el listado de la página de alimentadores, y seguirá teniendo su página de alimentador.
Si el alimentador fue ``deselegido'' y no ha vuelto a ser elegido (bien en la página principal, poniéndolo en el formulario de alimentadores, o bien en la págian de alimentadores, eligiéndolo), por cualquier usuario, el botón servirá para volver a alegirlo. Como esto tiene los misms efectos que si se hubiera puesto su nombre en el formulario de alimentadores de la página principal, si se pulsa el botón el alimentador quedará elegido, sus datos se actualizarán descargándolos del sistema de alimentadores correspondiente (YouTube, por ejemplo), y se recibirá la página de ese alimentador, con información actualizada.
\item ¿Tiene que haber una lista de alimentadores en la página de usuario?
En una primera versión del enunciado teníamos una lista de alimentadores en la página de usuario. Pero como esa lista ya está en varias otras páginas, y no tiene mucho sentido en esa (porque serían los alimentadores elegidos por cualquier usuario), en la versión final del enunciado no hay que incluir lista de alimentadores en la página de usuario. Sin embargo, puede ser una buena mejora opcional, si te interesa implementarla. Si lo haces, sería conveniente que sea la lista de alimentadores que ha seleccionado ese usuario en particular.
\item ¿Cómo puedo implementar la subida de la foto del usuario?
Para que el usuario pueda cambiar su foto, tendrás que implementar una vista que recoja la foto que se le envíe desde un formulario, y la almacene. El manual de Django indica cómo hacer eso para ficheros en general\footnote{``File uploads'' en la documentación de Django: \\ \url{https://docs.djangoproject.com/en/3.0/topics/http/file-uploads/} \\
Mira especialmente el apartado ``Handling uploaded files with a model'', pero en general será conveniente leer toda la página.}. Y puedes encontrar varias referencias en la red que explican cómo hacerlo específicamente para imágenes\footnote{Ejemplo de referencia que indica cómo subir imágenes a Django: \\
\url{https://coderwall.com/p/bz0sng/simple-django-image-upload-to-model-imagefield}}.
Resumiendo mucho, convendrá que utilices un campo de tipo \verb|ImageField|\footnote{Campo ``ImageField'' en la documentación de Django: \\ \url{https://docs.djangoproject.com/en/3.0/ref/models/fields/\#imagefield}} en la base de datos, especificando a qué directorio se subirán las imágenes (parámetro \verb|upload_to|). Para subir los ficheros, puedes utilizar un Django Form (heredando de \verb|forms.Form|) en el que especifiques un campo \verb|forms.ImageField()|, y una plantilla de formulario (elemento HTML \verb|form|) en la que especifiques que el método es POST y además un \verb|enctype| (tipo de codificación) \verb|multipart/form-data|. Cuando instancies el formulario Django, además del parámetro habitual (\verb|request.POST|), le pasarás también \verb|request.FILES|, que es donde vendrá la imagen (dado que usas \verb|multipart/form-data|). Después de validar la respuesta que te ha venido del formulario, extraes de ella el campo donde venga la imagen, y lo guardas en la base de datos. Al hacerlo, se guardará un descriptor en la base de datos, y la imagen se guardará (automáticamente) en el directorio que hayas especificado.
Trata de entender todo el proceso antes de ponerte a implementarlo, y cuidado con las recetas que podrás encontrar en Internet, porque puede que no te sirvan exactamente ``tal cual''.
\item ¿Qué quiere decir ``vídeo empotrado'', que se menciona en la información detallada para un vídeo de un canal de YouTube? ¿Cómo se hace?
``Vídeo empotrado'' es en ese caso la traducción de ``embedded video'', y quiere decir que el video aparezca directamente en la página, normalmente en un elemento \verb|iframe|. En el caso de YouTube, puedes obtener el código HTML para empotrar cualquier video si, cuando lo estás viendo en el navegador, pulsas el botón de compartir (``Share''), y eliges la opción ``Embed''. Esto muestra un código HTML como el siguiente:
\begin{verbatim}
<iframe width="560" height="315"
src="https://www.youtube.com/embed/HZOodD84MR8"
frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen></iframe>
\end{verbatim}
Basta con que en él cambies el código del video (en este caso ``HZOodD84MR8'' por el del video que quieres empotrar, y ya está.
\item En la página de cada alimentador, ¿hay que mostrar los datos en formato resumido o detallado?
Había una errata en el enunciado que no dejaba claro este extremo. Ahora debería quedar claro: en la página de cada alimentador habrá un listado de los items de ese alimentador, en formato resumido, incluyendo también para cada item un enlace a la página del item.
\item En el formulario para elegir alimentador, ¿qué hay que introducir? (el nombre de los alimentadores que ya hay, dar opciones de los que ya hay, directamente el identificador de alimentador...).
Habrá un formulario por cada tipo de alimentador. Por ejemplo, uno para canales de YouTube, otro para etiquetas de Flickr, etc. Cada uno de ellos será un formulario en el que se podrá poner lo que haga falta para elegir un alimentador para ese tipo de alimentador. Por ejemplo, en el caso de YouTube, el formulario tendrá una caja de texto para poder poner el id del canal, y un botón para enviarlo. Lo normal, es que todos los formularios para los tipos de alimentadores que hayas implementado estén juntos.
Alternativamente, y esto es opcional, se puede tener un único formulario para todos los tipos de alimentador. En ese caso, tendrás que tener algo parecido a un menú desplegable para que puedas elegir qué tipo de alimentador vas a indicar, algún elemento para poner el identificador (id, etiqueta, nombre de sección... lo que sea), y un botón para enviar.
Para algunos alimentadores (por ejemplo, el de TuCanaldeSalud), puede tener sentido que el formulario incluya un menú par elegir el alimentador, pero este no es el caso de ninguno de los alimentadores obligatorios. Puede ocurrir esto cuando el número de alimentadores a elegir sea pequeño.
\item ¿Es necesario utilizar los mecanismos provistos por Django para el control de sesiones y autenticación?
En principio, esa es la solución recomendada. El principal problema suele ser asegurarse de que cualquier mecanismo alternativo funciona al menos tan bien como el de Django, lo que no es en general trivial. De todas formas, salvo muy buenos motivos, la aplicación es una aplicación Django, y por lo tanto cuantas más facilidades de Django se usen (bien usadas), mejor.
\item Los archivos CSS que pueden modificar los usuarios, ¿dónde y cómo debemos guardarlos?
La forma recomendada de hacerlo es mediante plantillas:
\begin{itemize}
\item En el directorio de plantillas incluirías una para la hoja CSS del sitio. Esa plantilla tendría como variables de plantilla los valores que quieras que los usuarios puedan cambiar (color de tipo de letra, tamaño de tipo de letra, etc.).
\item Además, para cada usuario, tendrás una tabla en la base de datos donde se almacenarán los valores para ese usuario (normalmente, una fila de la tabla por usuario).
\item Tendrás una vista en views.py que se encargará de generar la hoja CSS a partir de la plantilla. Esa vista es la que comprobará si la petición que está atendiendo corresponde a un usuario (en cuyo caso tendrá que obtener los valores para ese usuario de la tabla anterior), o no (en cuyo caso usará valores por defecto). Con los valores que obtenga, generará la hoja CSS a partir de la plantilla anterior.
\item Por último, en urls.py tendrás una línea para indicar que si te piden el recurso que sirve la hoja de estilo, llamas a la vista anterior.
\end{itemize}
\item ¿Dónde puedo realizar el despliegue de la aplicación?
El despliegue puede realizarse en cualquier ordenador que esté conectado permanentemente a Internet durante el periodo de corrección, en una dirección accesible desde cualquier navegador conectado a su vez a Internet. Esto puede ser por ejemplo un ordenador personal en un domicilio con acceso permanente a Internet, adecuadamente configurado (puede ser una Raspberry Pi o similar, si se busca una solución simple y de bajo coste). También puede ser un servicio en Internet, por ejemplo uno gratuito como los que ofrecen Google (instrucciones\footnote{GCP Quickstart Using a Linux VM:\\ \url{https://cloud.google.com/compute/docs/quickstart-linux}}, precios\footnote{Google Compute Engine Pricing:\\ \url{https://cloud.google.com/compute/pricing}}), o PythonAnywhere (instrucciones\footnote{Capítulo ``Deploy!'' de Django Girls Tutorial:\\ \url{https://tutorial.djangogirls.org/en/deploy/}}, precios\footnote{PythonAnywhere Plans and Pricing:\\ \url{https://www.pythonanywhere.com/pricing/}}). Los profesores podremos ayudar de forma más detallada con PythonAnywhere.
\end{itemize}