Tip:
Highlight text to annotate it
X
Hablemos de la solución al problema extra, que era añadir "version history."
Esto funciona así: Si hago click en "History"
podemos ver las versiones anteriores de esta página.
Si creara una nueva versión de esta página, podría hacer clic en estos links de "editar".
Si hago clic en "Guardar", vemos que edité la página.
Si hago clic en "History" otra vez, vemos la nueva versión 3.
Pueden ver el contenido de la página aquí arriba.
Esa era la primera característica requerida para obtener los puntos extra,
es decir, ver el historial de todas estas páginas.
La segunda característica es ver cualquier versión particular de esto.
No puedo ir simplemente a /newpage. También tengo que decir qué versión es.
Si voy a esta versión intermedia aquí, voy a "newpage"
y luego agrego un parámetro get especificando qué version es.
En este caso, es la versión 5.
Ese es el Id de la base de datos.
Creo que esta es la versión 10, porque he creado otros objetos.
Google está asignando los IDs, y no importa mucho.
Ahora, por supuesto, puedo editar cualquiera de estas versiones.
Tienen su propio URL especial.
Aquí estamos editando newpage, v4, la cual es esa primera versión.
Si guardara esto, sobrescribiría la versión más nueva.
Si voy a ver el historial otra vez, vemos que está encima.
Si sólo quiero guardar la versión más reciente, puedo hacer clic en editar, guardar,
y aquí está nuestra página otra vez,
y si vamos al historial, podemos ver la historia completa.
Esto está bastante bueno. Hablemos de la implementación.
En primer lugar, hay varias maneras de hacer esto.
Podrías tener una página que tenga, en vez de contenido, una lista de contenidos.
Hay una forma de almacenar listas de cosas en un almacén de datos.
Esa es una buena forma de hacerlo.
Lo que yo hice fue esto:
Cada página tiene un nombre, que siempre va a ser "pages"
y tiene un "padre" llamado /root, más la ruta.
Puse /root allí porque pensé que esto iba a ser más complicado de lo que lo fue.
Recuerda que las entidades en el almacén de datos pueden tener estos ancestros,
esta jerarquía de objetos. No necesitamos pasar mucho tiempo hablando acerca de esto.
Comprender este punto no es necesario para poder completar esta tarea,
porque hay muchas maneras de resolver el problema.
Esta es la forma en que yo decidí hacerlo.
Cada URL tiene, básicamente, este ancestro común.
Entonces, cuando buscamos una página por ruta,
todo lo que estoy haciendo es decir
"busca todas las páginas que tengan este ancestro".
Es decir, "dame todas las páginas que pertenezcan a este URL,
organizadas de más reciente a más antigua".
Luego uso "get" para conseguir la más reciente.
Si quiero obtener una versión más antigua, uso la función getbyid,
que requiere un ID, y también requiere una "parent key",
la cual usa la misma llave que el query de ruta principal.
Esto dice "llévame a la página, en este caso 'class' se refiere a la página,
porque es el método de clase y estamos en la página
llévame a la página, en función del ID. Esto es parte del almacén de datos.
Quiero este ID y este padre.
Así que podemos conseguir versiones más antiguas en el historial
Y cuando estamos reproduciendo esto, como puedes ver en EditPage.
Puedo usar by_path y luego convocar "get"
para obtener la primer respuesta de esta búsqueda,
o puedo buscar el parámetro v, que es la versión.
Si está allí y es un dígito, es decir si es válido, intenta ejecutar by_id en él.
Si no está allí, significa que esa versión no existe. 'No hallada'.
De otro modo, si no hay parámetro v, simplemente busca la versión normal.
Tenemos el mismo bloque de código en la página wiki normal,
para ver cualquier página en el wiki.
Este mismo bloque de código, y por supuesto, queremos resolver este punto.
El código que te daré seguramente no será tan desprolijo.
Echémosle un vistazo a algunas de estas plantillas así podemos ver
la última parte de cómo es que todas estas cosas funcionan cuando las unes.
Estoy usando la plantilla heredada una vez más.
Mi plantilla base tiene el título del wiki.
Hace referencia a mi hoja de estilo, y tiene la estructura básica de mi documento,
lo cual va a tener una etiqueta de "body" y un par de "div"s
Estas clases son estilísticas, no son obligatorias para completar esta tarea.
Sólo son requisito para hacer que tu tarea sea un poco más prolija.
Quiero que mi trabajo se vea bastante bien, así que yo las uso.
Esta es el área total de encabezado, donde creamos esos links.
Si hay un usuario, imprimimos el nombre de usuario
y luego el link de cerrar sesión,
que es un link básico de /logout.
Si el usuario no ha iniciado sesión, creamos dos links,
uno para iniciar sesión y otro para registarse.
Esos también son links básicos.
Ambos tienen el estilo de link gris, que es como los hago grises,
y hago que esa cosa de subrayar funcione.
Tengo aquí este "div" que básicamente está vacío.
Esto es un bloque.
Recuerda que esta es una manera de hacer este tipo de plantillas de herencia,
así no tienes que escribir el mismo HTML una y otra vez.
Otras plantillas heredadas de la base completarán este bloque.
Aquí es donde ponemos controles para editar una página o ver el historial de una página.
Todo eso es sobrescrito en otras plantillas.
Esta técnica de "clear div"...
la técnica que uso para hacer que los links floten a la derecha se llama "float".
Cuando haces que algo flote, no ocupa nada de espacio.
Una de las técnicas para hacer que ocupe espacio es usar este "clear div".
No voy a intentar explicarlo aquí, pero es básicamente un truco de CSS para
hacer que algo flote al borde de la página, y hacer que aún tenga altura vertical.
Aquí tenemos el verdadero contenido.
Aquí es donde va a ir la ventana de edición, o la página de contenido wiki.
Y no hay contenido aquí. Simplemente definimos el bloque y las otras plantillas lo anularán.
Veamos la plantilla para page html que obtiene la verdadera página de contenido wikil
Extiende base.html, que dice "usa todo lo demás, y luego podemos anular los dos bloques"
En una página de vista, una página wiki normal, hay dos links
Uno para editar, y uno para ver el historial
Pero sólo mostramos el link de editar si el usuario ha iniciado sesión
Si ha iniciado sesión, mostramos el link de editar,
pero mostramos el link de "historial" aunque no lo haya hecho.
Y estos dos links son simples. Uno es _edit y la ruta.
Recuerda que la ruta pasó por mi función "render".
Y el otro es _history a la ruta.
Ambos son enlaces simples que son manipulados por el "handler" apropiado.
Luego, en el contenido real, "rendeamos" el contenido de la página.
Estoy usando la notación jinja segura,
que dice "no dejes escapar esto", e indica que se debe tomar el html que fue tipeado
e insertarlo en la página.
No hay problemas de seguridad, ya que yo ingresé todo el html, y sé que está bien.
Ahora, si vas a poner este sitio web en internet, sería bueno tener algún tipo especial de escape.
Muchos websites sólo admiten algún tipo de html,
o algún otro lenguaje especial que se convierte en html,
o no admiten html en absoluto, pero eso no permitiría usar links, y así el wiki no sería útil.
Ese es un problema de diseño, y depende de ti.
"Edit html", esta es nuestra plantilla para la página de edición.
Los controles son muy similares a los de la página de vista
Tenemos un link llamado "view" que conecta con la propia página,
y funciona como un botón de "cancelar"
Luego tenemos un link al historial de la página donde puedes verlo desde la página de edición.
Estos son enlaces básicos y sólo creamos estos links si la página ya existe.
Si estás creando una página nueva, no hay nada para ver, y no hay historial;
esto es lo que "if page" ha hecho.
Y recuerda que cuando convocamos esta plantilla, informamos sobre la existencia de la página.
Este es mi formulario, es un método "post", tiene esta clase, llamada "main edit" para propósitos
estilísticos, para que se vea bien y grande.
Es un área de texto gigante, cuyo nombre es "content" e incluye page y page.content.
Así que, si la página existe, entrega contenido. De otra forma, devuelve una "string" vacía.
Eso es lo que ocurre.
Hacia el final del formulario, hay un área pequeña llamada "form footer"
que tiene el botón de seguridad
y revisa todo ese CSS.
La página de edición también es bastante simple.
La página de historial es para ver la historia de una página wiki.
Una vez más, tenemos los controles. Si el usuario existe, creamos el link de edición,
igual que en la página wiki de vista principal.
Sin importar si el usuario ha ingresado sesión,
creamos el link para ver la página, en vez del historial.
Para el contenido, estoy creando una tabla.
No hemos visto casi nada de las tablas en esta clase
así que usa los ejemplos que te he dado.
Hace lo que esperarías que hiciera, crea una tabla.
Dibujamos una tabla, "history table" es lo que usé para darle estilo.
Te mostraré de nuevo esa función llamada "gray style"
que hace esto: para las "p" y "posts" devuelve la "p" e informa si esa fila es par o impar.
Así es como logro ese efecto, por el cual una fila es blanca y la siguiente gris.
Te mostraré el efecto primero.
Aquí está. Esta es la página de historial
Puedes ver que la primer fila es blanca, la segunda gris, blanca, gris, blanca.
Es un lindo efecto cuando tenemos una tabla.
Yo hice una versión simple de esto.
El código para generar cuál de estas filas debería ser gris, es algo así:
Esta es la función "gray style".
Veremos esto en la plantilla una vez más, pero lo que hace es tomar una lista y enumerarla.
Esta es una función de Python incorporada, que indica "devolver los elementos de una
lista en una tupla junto con el índice de ese elemento en la lista".
Para "x" en "list", devolverá básicamente cada página. Página 1, página 2, página 3.
Para n, x en "enumerate list" dice "indexar en la lista 0, página 1, 0, página 2, como tuplas".
Si "n" es "modulo 2 = 0", es decir, si es par, la fila debería estar vacía, o devolver "x" y " ".
Y si es impar, devolvería "x" y "gray"
Muchas cosas ocurren en esta función.
También usa "yield", que es como construimos generadores
Esto es bastante complejo, y no es requisito para la tarea, pero así es como yo cree ese efecto.
También puedes crear ese efecto en la plantilla en sí, usando una variable que tú creas,
y luego verificas si es par o impar.
Esta es la forma más "Pythonica" de hacerlo.
De vuelta a la plantilla, "p rowstlye" va a ser una string en blanco o la string "gray".
Luego uso esto en el nombre de la clase para cada fila.
Cada fila va a tener una clase " " o la palabra "gray", y así es como en el CSS
decido si debo hacer que la fila sea gris o no.
Entonces, tenemos tres columnas, eso es lo que TD hace.
La primer columna es la fecha, así que imprimo la última hora de modificación.
La segunda columna es el contenido. Imprimo los primeros 100 caracteres del contenido
y la siguiente columna es un enlace normal, que tiene el link "gray style"
lo cual lo hace verse parecido a mis otros links.
Después tenemos los puntos href hacia la ruta, y luego añado un parámetro gip
"v= " y el ID de ese post
Recuerda, .key.ID es como conseguir el ID de un elemento en el almacén de datos de Google,
o de una entidad.
El URL es la ruta de la página en que estamos, más el ID almacenado en el parámetro v.
Vimos en los handlers "edit" y "wiki" buscamos ese parámetro v
para ver si podemos encontrar un ítem específico.
Si seguimos hacia abajo, si el usuario está en su sesión, "if user" creamos el link "edit".
Este es un link llamado "edit" que conecta con /_edit,
que es el mismo link que esta aquí arriba.
"Path", "v= " y luego incluimos la idea de la página.
Probablemente debería organizar esto.
Debería tener una función o una página que diga "editar URL",
"history URL", "normal URL", "versión URL", eso sería muy útil y debería incluirlo en la plantilla.
Ese es uno de los primeros cambios que voy a hacer, porque esto puede llevar a errores.
Tenemos estas dos líneas que son básicamente iguales, y no es bueno estar
en esta situación, porque si edito una debo recordar editar la otra, etc., etc...
Entonces cerramos nuestro frase "if", nuestra "four loop" y nuestra tabla,
y así es como creamos la página de historial.
Esas son todas las plantillas.
Te mostraré rápidamente el CSS que uso para dar estilo a las cosas y terminamos.
Primero "html". Recuerda, fuera del elemento del cuerpo está el elemento html
de altura 100%, y esto es lo que me permite hacer que el área de texto en la página de edición
ocupe toda la página. Echémosle un vistazo.
Si hago clic en "edit" aquí arriba, para hacer que esta área de texto ocupe el buscador entero es
hacer que el html, que usualmente es del tamaño del contenido, ocupe 100% del espacio.
Eso es lo que hace el 100%.
El elemento de cuerpo también necesita ser 100%, por la misma razón.
"Position relative" se usa cuando necesitas ajustar dònde aparecen las cosas,
en relación a donde deberían aparecer,
o si necesitas una posición relativa a un elemento padre de un elemento que vas a ajustar
absolutamente, que es lo que haces cuando algo debe posicionarse específicamente en la página.
Elijo mi fuente, el tamaño por defecto, el ancho del documento completo, que son 800 píxels.
"Margin: 0 auto" es básicamente "centrar".
Nuestro color de fuente por defecto es gris para todo el texto.
El área de encabezado de la página es 30 píxels de alto, la altura de la línea es 30,
lo cual causa que el texto quede centrado verticalmente.
Obtenemos un margen de 10 pixeles para el contenido.
El elemento de control "flota" a la derecha. Esos son los links para editar, ver, e historial
que aparecen aquí en el buscador.
"Float right" toma el contenido y lo hace "flotar" a la derecha.
Y es gris, tamaño de fuente 13.
Los controles siguiendo controles crean un poco de espacio entre ellos. Recuerda que tenemos
controles separados para "Login"y "Sign up" y para las acciones de la página,
y añadimos un poco de espacio.
Te mostraré esto rápidamente.
Aquí, estos son esos 20 píxels, entre esas dos cosas, este es un elemento de control,
y este es otro, y ambos han "flotado" a la derecha, entonces se acumulan allí.
Eso es lo que hacen estas dos cosas.
Usamos "gray link", por todos lados para que los enlaces sean grises y no queden subrayados.
Si alguien los visita, en vez de cambiar a púrpura, quedan en gris.
Si el mouse está sobre ellos, eso es lo que hace "hover", crear una línea de subrayado,
así que el comportamiento es algo así:
cuando pongo el mouse sobre "Log out" puedes ver que aparece el subrayado
y todos nuestros links tienes ese efecto. Es un efecto que me gusta.
Puedes ver que usé "gray link"en todos estos estilos también, así el subrayado aparece
cuando el mouse está sobre ellos, y puedes hacer todo esto en CSS.
Los errores deberían ser rojos. Usamos esto todo el tiempo.
la clase "Main edit" está en el formulario principal y tiene una posición absoluta que me permite
forzar el posicionamiento de este elemento,
así que puedo decir "posicionar a 45 píxels" del comienzo de la página,
0 píxels de la derecha, 10 desde el final, 0 desde la izquierda,
y esto hace que el formulario ocupe todo el espacio.
El área de texto debajo de "main edit" es lo mismo, excepto que está a 0 píxels del comienzo,
30 del final, lo cual nos da lugar para el botón, y luego 0 píxels de la izquierda, 0 de la derecha.
Eso hace que nuestra área de texto ocupe casi todo el formulario.
El pie de página del formulario está posicionado absolutamente y eso es al final, 0 píxels del final,
0 píxels de la izquieda, 0 de la derecha.
No especifiqué la parte superior, lo que significa que será dibujado normalmente,
e indiqué una altura de 30 píxels,
que dibuja una fila a lo largo de la parte inferior para un botón de "Guardar" de 30 píxels de alto.
Nuestro botón de "Submit" es de tamaño de fuente 18 píxels.
Esta es nuestra tabla. "Border Collapse" encoge un poco la tabla, de otra manera, las tablas tienen
cierto espaciado por defecto entre cada celda.
Si una tabla tiene un atributo CSS gris, que es como creamos filas alternativas,
hacemos que el color de fondo sea "eee", que es gris claro.
Si es una celda de fecha, el ancho es 200 píxels.
Si es una celda de contenido, agrega un poco de relleno, para engordar nuestra tabla un poquito.
Si es una celda para links, rellena un poco abajo, a la izquierda, y a la derecha, 10 píxels.
Si lo haces así, el primer número es relleno vertical, el cual es "0",
y esto es relleno horizontal, 5 píxels, lo cual genera este efecto.
Los pequeños 5 píxels entre "view" y "edit", si me deshiciera de ellos,
no habría espacio entre las palabras, porque es una tabla, y ellos crean ese pequeño espacio.
Eso es todo. Ya sé que es un montón de información.
No hablamos de CSS en este curso, pero me gustaría mostrártelo, por si tienes preguntas.
Proveeré el CSS y puedes jugar con él en tus proyectos, y eso es todo para el examen final.
Si pudiste resolver todo esto tú solo, estoy muy impresionado.
Sé que el material del examen final era desafiante,
y la pregunta extra de crear el historial era bastante complicada
Así que si pudiste hacer que todo esto funcionara, hiciste un muy buen trabajo.
Es genial, y es una señal de que has aprendido mucho en esta clase.
Para aquellos que no pudieron resolverlo,
o no lo intentaron, esto es algo que deberían aspirar a poder hacer en el futuro.
Eso es todo para esta clase. Quiero agradecerles
por haber llegado conmigo hasta aquí. Ha sido una experiencia muy divertida,
y espero que hayan aprendido tanto como yo.
Las últimas semanas han sido muy divertidas.
¡Nos vemos en algún lugar en internet, y buena suerte!