diff --git a/LANGS.md b/LANGS.md index 7fdad21706e..3add961c8ef 100644 --- a/LANGS.md +++ b/LANGS.md @@ -1,3 +1,4 @@ * [English](en) * [Polski](pl) * [Український](uk) +* [Español (beta)](es) diff --git a/es/CONTRIBUTING.md b/es/CONTRIBUTING.md new file mode 100755 index 00000000000..2bb0b745e82 --- /dev/null +++ b/es/CONTRIBUTING.md @@ -0,0 +1,109 @@ +# ¿Cómo contribuir? + +The Django Girls Tutorial está licenciado bajo la licencia internacional*Creative Commons Attribution-ShareAlike 4.0*. Cualquiera puede añadir, editar y corregir el tutorial. + +# Editar lo basico + +El código fuente del tutorial se encuentra [en Github](http://github.com/DjangoGirls/tutorial). Para aceptar y revisar cambios se usa el la guía [Fork & Pull workflow](https://help.github.com/articles/using-pull-requests) de Github. + +El tutorial utiliza el servicio de [GitBook](https://www.gitbook.io/) para la publicación de su documentación. Visita el siguiente enlace para [ver más información acerca de cómo funciona Gitbook](http://help.gitbook.io/). + +El tutorial esta escrito en [el lenguaje de marcado Markdown](https://help.github.com/articles/markdown-basics). + +Puedes encontrar todas las discusiones sobre el contenido del tutorial en el [issue tracker](https://github.com/DjangoGirls/tutorial/issues) de Github. + +# Primeros pasos y requisitos previos + +Para contribuir en el tutorial es necesario que cuente con lo siguiente: + + * Una [cuenta de Github](https://github.com) + * En el caso de hacer una edición compleja, estar familiarizado con [los conceptos básicos de línea de comandos de Git](https://help.github.com/articles/set-up-git) o familiarizado con una aplicación ([Windows](https://windows.github.com/), [Mac](https://mac.github.com/)) que te permita enviar los cambios realizados en tu computadora a Github. + +## Hazle Fork al repositorio + +Primero hazle Fork al repositorio de [DjangoGirls/tutorial](https://github.com/DjangoGirls/tutorial) hacia tu cuenta personal de Github: + +![Fork button](contributing/images/fork.png) + +# Editando el contenido de un capitulo + +## Pequeños cambios + +Para pequeños cambios como correcciones puedes usar el editor online de Github: + + * Abre el fork que hiciste a tu cuenta de Github + * ve al archivo *README.md* en cualquiera de los capitulos, + * Presiona el icono de *editar* (lápiz) + +así puede editar el capitulo directamente desde github.com. + +![Edit button](contributing/images/edit.png) + +La sintaxis de Markdown es usada para editar las paginas individuales del tutorial. + +![Github editor](contributing/images/github_editor.png) + +Guarda tus cambios y crea una pull request como se explicara más adelante. + +## Contenidos nuevos y cambios complejos + +Para añadir nuevos capitulos, escribir pequeños fragmentos de texto o añadir imagenes, necesitaras hacer una copia del tutorial en tu computadora local. + +O bien utilizar la aplicación Github para su sistema operativo (antes mencionado) o la linea de comando de `git` para obtener el repositorio de manera local. Obtendrá la dirección del repositorio de la pagina principal de su propio Fork del repositorio en Github: + + git clone git@github.com:tu_usuario_de_github/tutorial.git + + +descarga la aplicación del [editor de Gitbook](http://help.gitbook.io/editor/README.html) para tu computadora. + +A continuación, puedes abrir el tutorial en el Editor de Gitbook (*File* > *Open book*). + +![Gitbook](contributing/images/gitbook.png) + +Haz todos los cambios que quieras en el tutorial usando el editor y luego guardalos(*Book*>*Save All*). + +Luego haz un commit para los cambios usando `git` y envía los cambios hacia tu repositorio remoto de Github. + +Ejemplo: + + $ git status + On branch contributing + Untracked files: + (use "git add ..." to include in what will be committed) + + contributing_and_editing_this_book/images/gitbook.png + + $ git add contributing_and_editing_this_book/images/gitbook.png + + $ git commit -m "Added gitbook editor screenshot" + [contributing fe36152] Added gitbook screenshot + 1 file changed, 0 insertions(+), 0 deletions(-) + create mode 100644 contributing_and_editing_this_book/images/gitbook.png + + $ git push + Counting objects: 11, done. + Delta compression using up to 8 threads. + Compressing objects: 100% (5/5), done. + Writing objects: 100% (5/5), 266.37 KiB | 0 bytes/s, done. + Total 5 (delta 1), reused 0 (delta 0) + To git@github.com:miohtama/tutorial.git + b37ca59..fe36152 contributing -> contributing + + +# Hacer un pull request + +Después de finalizar los cambios necesitaras crear [una pull request](https://help.github.com/articles/using-pull-requests) en Github. DjangoGirls será informado acerca de la pull request, revisara tus cambios, sugerirá cualquier corrección sí la necesita y luego hara un *pull* a tus cambios hacia la versión original. + +En tu propio repositorio de Github presiona el botón *Compare & pull request* + +![Gitbook](contributing/images/pull_request.png) + +Rellena la información de *por que* fueron hechos estos cambios. el inspector analizará los detalles de los cambios actuales, de esta forma no necesitas repetir el contenido de los cambios. + +Luego presiona *Create pull request*. + +Github le notificara a través de e-mails el seguimiento del proceso. + +# Más información y ayuda + +Para cualquier duda póngase en [contacto con DjangoGirls](http://djangogirls.org/). \ No newline at end of file diff --git a/es/README.md b/es/README.md new file mode 100755 index 00000000000..8a638de9f88 --- /dev/null +++ b/es/README.md @@ -0,0 +1,53 @@ +# Tutorial de Django Girls + +[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +> Este trabajo esta licenciado bajo la licencia internacional Creative Commons Attribution-ShareAlike 4.0. Para ver una copia de esta licencia, visita el siguiente enlace http://creativecommons.org/licenses/by-sa/4.0/ + +## Translation + +This tutorial has been translated from English to Spanish by a group of awesome volunteers. Special thanks for help go to Joshua Aranda, Kevin Morales, Silvia Frias, Andrea Gonzales, Adrian Manjarres, Rodrigo Caicedo, Maria Chavez, Marcelo Manso, Rosa Durante, Moisés, Israel Martinez Vargas, Juan Carlos, N0890Dy, Khaterine Castellano, ZeroSoul13 and Erik Aguayo. <3 <3 + +## Introducción + +¿Te has sentido que el mundo está cada vez más cercano a la tecnología y de cierto modo te has quedado atrás? ¿Te has preguntado cómo crear un sitio web pero nunca has tenido la suficiente motivación para empezar? ¿Has pensado que el mundo del software is demasiado complicado para intentar hacer algo por tu cuenta? + +Bueno, Tenemos buenas noticias para ti! programar no es tan difícil como aparenta y queremos mostrarte cuán divertido que puede llegar a ser. + +Este tutorial no convertirá mágicamente en un programador. Sí quieres ser buena en eso, necesitaras meses o inclusos años de aprendizaje y práctica. sin embargo queremos mostrarte que programar o crear sitios web no es tan complicado como parece. Intentaremos explicarte en pequeñas partes tan bien como podamos, para que no te sientas intimidada por la tecnología. + +¡Esperamos poder hacerte amar la tecnología tanto como nosotras lo hacemos! + +## ¿Qué aprenderás con este tutorial? + +Una vez terminado el tutorial, tendrás una simple y funcional aplicación web: tu propio blog. Te mostraremos como ponerla online, así otros podrán ver tu trabajo! + +se verá (más o menos) como ésta: + +![Figura 0.1][2] + + [2]: images/application.png + +> Sí estás siguiendo este tutorial por tu cuenta y no tienes nadie que te ayude a resolver algún problema, tenemos un chat para ti: [![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/DjangoGirls/tutorial?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +. ¡Hemos pedido a nuestros coaches y asistentes anteriores estar ahi de vez en cuando para ayudar a otros con el tutorial! ¡No dudes dejar tus preguntas allí! + +Esta bien, [empecemos desde el inicio...][3] + + [3]: how_internet_works/README.md + +## Sobre nosotros y cómo contribuir + +Este turorial es mantenido por [DjangoGirls][4]. Sí encuentras algún error o quieres actualizar el tutorial por favor [sigue la guía de cómo contribuir][5]. + + [4]: http://djangogirls.org/ + [5]: https://github.com/DjangoGirls/tutorial/blob/master/CONTRIBUTING.md + +## ¿Te gustaría ayudarnos a traducir el tutorial hacia otros idiomas? + +Actualmente, las traducciones son llevadas a cabo en la formaleta crowdin.com, en el siguiente enlace: + +https://crowdin.com/project/django-girls-tutorial + +Sí tu idioma no aparece en la lista de crowdin, por favor [abre una nueva issue][6] informando el idioma así nosotros podemos añadirlo + + [6]: https://github.com/DjangoGirls/tutorial/issues/new diff --git a/es/SUMMARY.md b/es/SUMMARY.md new file mode 100755 index 00000000000..67a8f287221 --- /dev/null +++ b/es/SUMMARY.md @@ -0,0 +1,26 @@ +# Índice + +* [Introducción](README.md) +* [Cómo funciona el internet](how_internet_works/README.md) +* [Introducción a la línea de comandos](intro_to_command_line/README.md) +* [Instalación de Python](python_installation/README.md) +* [Editor de código](code_editor/README.md) +* [Introducción a Python](python_introduction/README.md) +* [¿Qué es Django?](django/README.md) +* [Instalación de Django](django_installation/README.md) +* [Comenzando un proyecto en Django](django_start_project/README.md) +* [Modelos en Django](django_models/README.md) +* [ORM de Django (Querysets)](django_orm/README.md) +* [Administrador de Django](django_admin/README.md) +* [Deploy!](deploy/README.md) +* [Django urls](django_urls/README.md) +* [Vistas de Django - es hora de crear!](django_views/README.md) +* [Introducción a HTML](html/README.md) +* [Datos dinámicos en plantillas](dynamic_data_in_templates/README.md) +* [Plantillas de Django](django_templates/README.md) +* [CSS - Hazlo bonito](css/README.md) +* [Extendiendo plantillas](template_extending/README.md) +* [Extiende tu aplicación](extend_your_application/README.md) +* [Formularios en Django](django_forms/README.md) +* [Dominio](domain/README.md) +* [¿Qué sigue?](whats_next/README.md) diff --git a/es/code_editor/README.md b/es/code_editor/README.md new file mode 100755 index 00000000000..72bcb5d920a --- /dev/null +++ b/es/code_editor/README.md @@ -0,0 +1,33 @@ +# Editor de código + +Estás a punto de escribir tu primera línea de código, así que es hora de descargar un editor de código! + +Hay muchos editores diferentes, cual usar depende mucho de la preferencia personal. La mayoría de programadores de python usan entornos de desarrollo integrado (IDEs) complejos, pero muy poderosos, como PyCharm. Sin embargo, como principiante, eso es probablemente menos conveniente; nuestras recomendaciones son igual de poderosas pero mucho mas simples. + +Nuestras recomendaciones están listadas abajo, pero siéntete libre de preguntarle a tu instructor cuales son sus preferencias - de esa forma será mas fácil obtener ayuda de ellos. + +## Gedit + +Gedit es un editor de código abierto, gratis, disponible para todos los sistemas operativos. + +[Descárgalo aquí][1] + + [1]: https://wiki.gnome.org/Apps/Gedit#Download + +## Sublime Text 2 + +Sublime Text es un editor muy popular con un periodo de prueba gratis. Es fácil de instalar y está disponible para todos los sistemas operativos. + +[Descárgalo aquí][2] + + [2]: http://www.sublimetext.com/2 + +## Atom + +Atom es un editor de código muy nuevo creado por [GitHub][3]. Es gratis, de código abierto, fácil de instalar y fácil de usar. Esta disponible para Windows, OSX y Linux. + + [3]: http://github.com/ + +[Descárgalo aquí][4] + + [4]: https://atom.io/ \ No newline at end of file diff --git a/es/css/README.md b/es/css/README.md new file mode 100755 index 00000000000..031c48b9b55 --- /dev/null +++ b/es/css/README.md @@ -0,0 +1,285 @@ +# CSS - ¡Hazlo bonito! + +Nuestro blog todavia se ve bastante feo, verdad? Es hora de hacerlo bonito! Vamos a usar CSS para eso. + +## ¿Qué es CSS? + +CSS ('Cascading Style Sheets', que significa 'hojas de estilo en cascada') es un lenguaje utilizado para describir el aspecto y el formato de un sitio web escrito en lenguaje de marcado (como HTML). Trátalo como maquillaje para nuestra página web ;). + +Pero no queremos empezar de cero otra vez, ¿verdad? Una vez más, usaremos algo que ya ha sido realizado por programadores y publicado en Internet de forma gratuita. Reinventar la rueda no es divertido, ¿Sabes? + +## ¡Vamos a usar Bootstrap! + +Bootstrap es una de las herramientas (framework) HTML y CSS más populares para desarrollar webs bonitas: http://getbootstrap.com/ + +Fue escrito por programadores que trabajaban para Twitter y ahora colaboran en él desarrolladores voluntarios de todo el mundo. + +## Instalar Bootstrap + +Para instalar Bootstrap, tienes que añadir esto al `< head >` en el archivo `.html` (`blog/templates/blog/post_list.html`): + + + + + + +Esa línea no incluye ningún fichero a tu proyecto, simplemente utiliza uno existente en internet. Adelante, abre tu página web y actualízala. ¡Ahí lo tienes! + +![Figure 14.1][1] + + [1]: images/bootstrap1.png + +¡Se ve mucho mejor! + +## Archivos estáticos en Django + +Otra cosa que aprenderás hoy se llama **archivos estáticos**. Las paginas estáticas son todo tu CSS e imágenes -- archivos que no son dinámicos, es decir, su contenido no depende del contexto de la petición y será el mismo para todos los usuarios. + +CSS es un fichero estatico, así que para reflejar las modificaciones que se realicen en CSS necesitamos primero configurar archivos estáticos en Django. Solo tendrás que hacerlo una vez. Empecemos: + +### Configurar archivos estáticos en Django + +En primer lugar, necesitamos crear un directorio para almacenar nuestros archivos estáticos. Adelante, crea un directorio llamado `static` dentro de tu directorio `djangogirls`. + + djangogirls + ├─── static + └─── manage.py + + +Abre el fichero `mysite/settings.py`, desplázate hasta el fondo del fichero y agregue las siguientes líneas: + + STATICFILES_DIRS = ( + os.path.join(BASE_DIR, "static"), + ) + + +De esta manera Django sabrá dónde encontrar los archivos estáticos. + +## ¡Tu primer archivo CSS! + +Vamos ahora a crear un fichero CSS para añadir tu propio estilo a tu página web. Crear un nuevo directorio llamado `css` dentro de tu directorio `static`. Crea un nuevo fichero llamado `blog.css` dentro de este directorio `css`. Listo? + + static + └─── css + blog.css + + +Hora de escribir CSS! Abra el archivo `static/css/blog.css` en el editor de código. + +No nos adentraremos mucho en la personalización y aprendizaje sobre CSS aquí porque es muy fácil y lo puedes aprender por tu cuenta después de este taller. Recomendamos enormemente hacer este [curso de HTML y CSS en Codecademy][2] para aprender todo lo que necesitas saber sobre cómo hacer tus sitios web más bonitos con CSS. + + [2]: http://www.codecademy.com/tracks/web + +Pero vamos a hacer un poco al menos. ¿Tal vez podríamos cambiar el color de nuestro titulo? Para entender los colores, las computadoras utilizan códigos especiales. Empiezan con `#` y siguen con 6 letras (A-F) y números (0-9). Puedes encontrar los códigos de color, por ejemplo, aquí: http://www.colorpicker.com/. También puedes utilizar [colores predefinidos][3], tales como `rojo` y `verde`. + + [3]: http://www.w3schools.com/cssref/css_colornames.asp + +En el fichero `static/css/blog.css` debes añadir el siguiente código: + + h1 a { + color: #FCA205; + } + + +`h1 un` es un Selector de CSS. Esto significa que estamos aplicando nuestros estilos a `cualquier elemento dentro de un elemento h1` (por ejemplo cuando tenemos en código algo como: `< h1 >< a href = "" > enlace < /a >< / h1 >`). En este caso, estamos diciendo que cambie su color a `#FCA205`, que es de color naranja. Por supuesto, puedes poner tu propio color aquí! + +En el fichero CSS se definen los estilos de los elementos que se encuentran en el fichero HTML. Los elementos se identifican por el nombre del elemento (es decir, `a` `h1`, `body`), el atributo `class` o el atributo `id`. Class y id son nombres que le das al elemento tu mismo. Classes definen grupos de elementos y ids apuntan a elementos específicos. Por ejemplo, la siguiente etiqueta puede identificarse mediante CSS usando el nombre `a`, la clase `external_link` o el id `link_to_wiki_page`: + + + + +Leer sobre [Selectores de CSS en w3schools][4]. + + [4]: http://www.w3schools.com/cssref/css_selectors.asp + +Entonces, necesitamos decirle a nuestra plantilla HTML que hemos añadido CSS. Abra el fichero `blog/templates/blog/post_list.html` y añade esta línea al principio: + + {% load staticfiles %} + + +Estamos cargando archivos estáticos aquí:). Luego, entre el `< head >` `y/< / head >`, después de los enlaces a los archivos CSS Bootstrap (el navegador lee los archivos en el orden que los das, así que nuestro archivo de código puede sobreescribir partes del código en de Bootstrap), añade la siguiente línea: + + + + +Le acabamos de decir a nuestra plantilla donde se encuentra nuestro archivo CSS. + +Tu archivo ahora debe verse así: + + {% load staticfiles %} + + + Django Girls blog + + + + + + +
+

Django Girls Blog

+
+ + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} + + + + +OK, guarde el archivo y actualiza el sitio! + +![Figure 14.2][5] + + [5]: images/color2.png + +¡ Buen trabajo! Tal vez también nos gustaría dar un poco de aire a nuestro sitio web y aumentar el margen en el lado izquierdo. Vamos a intentarlo! + + body { + padding-left: 15px; + } + + +Añade esto a tu CSS, guarda el archivo y mira cómo funciona! + +![Figure 14.3][6] + + [6]: images/margin2.png + +¿Tal vez podemos personalizar la tipografía en nuestra cabecera? Pegue esto en `< head >` del archivo `blog/templates/blog/post_list.html`: + + + + +Esta línea va a importar una tipografía llamada *Lobster* de Google Fonts (https://www.google.com/fonts). + +Ahora agrega la linea `font-family: 'Lobster';` en el archivo CSS `static/css/blog.css` dentro del bloque `h1 a` (el codigo entre las llaves `{` and `}`) y actualiza la página: + + h1 a { + color: #FCA205; + font-family: 'Lobster'; + } + + +![Figure 14.3][7] + + [7]: images/font.png + +Genial! + +Como se mencionó anteriormente, CSS tiene un concepto de clases, que básicamente permite nombrar una parte del código HTML y aplicarle estilos solo a esa parte, no afectara a los otros. Es super útil si tienes dos divs, pero están haciendo algo muy diferente (como tu header y tu post), así que no quieres que se vean de la misma forma. + +Adelante! Nombra algunas partes del código HTML. Añade una clase llamada `page-header` a tu `div` que contiene el encabezado, así: + + + + +Y ahora añade la clase `post` a tu `div` que contiene una entrada del blog. + +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ + +Ahora añadiremos bloques de declaración a diferentes selectores. Selectores a partir de `.` se refieren a las clases. Hay muchos tutoriales y explicaciones sobre CSS en la web para ayudarte entender el siguiente codigo. Por ahora, sólo copia y pega en tu archivo `mysite/static/css/blog.css`: + + .page-header { + background-color: #ff9400; + margin-top: 0; + padding: 20px 20px 20px 40px; + } + + .page-header h1, .page-header h1 a, .page-header h1 a:visited, .page-header h1 a:active { + color: #ffffff; + font-size: 36pt; + text-decoration: none; + } + + .content { + margin-left: 40px; + } + + h1, h2, h3, h4 { + font-family: 'Lobster', cursive; + } + + .date { + float: right; + color: #828282; + } + + .save { + float: right; + } + + .post-form textarea, .post-form input { + width: 100%; + } + + .top-menu, .top-menu:hover, .top-menu:visited { + color: #ffffff; + float: right; + font-size: 26pt; + margin-right: 20px; + } + + .post { + margin-bottom: 70px; + } + + .post h1 a, .post h1 a:visited { + color: #000000; + } + + +Luego envuelve el código HTML que muestra los mensajes con las declaraciones de clases. Cambia esto: + + {% for post in posts %} +
+

published: {{ post.published_date }}

+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} + + +En `blog/templates/blog/post_list.html` con esto: + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} +
+
+
+ + +Guarda los archivos y actualiza tu sitio. + +![Figure 14.4][8] + + [8]: images/final.png + +Woohoo! Parece increíble, ¿verdad? El codigo que acabamos de pegar no es tan difícil de entender y debes de ser capaz de entender la mayoría sólo con leerlo. + +No tengas miedo de jugar un poco con este CSS e intentar cambiar algunas cosas. Si rompes algo, no te preocupes, siempre puedes deshacerlo! + +De todos modos, recomendamos que realices el curso curso gratuito [Codeacademy HTML & CSS][2] como tarea que para aprendas todo lo que necesitas acerca de hacer tus sitios web bonitos con CSS. + +¡¿Lista para el siguiente capítulo?! :) \ No newline at end of file diff --git a/es/css/images/bootstrap1.png b/es/css/images/bootstrap1.png new file mode 100644 index 00000000000..f7e1f57536c Binary files /dev/null and b/es/css/images/bootstrap1.png differ diff --git a/es/css/images/color2.png b/es/css/images/color2.png new file mode 100644 index 00000000000..c191d399356 Binary files /dev/null and b/es/css/images/color2.png differ diff --git a/es/css/images/final.png b/es/css/images/final.png new file mode 100644 index 00000000000..f90070b1aa5 Binary files /dev/null and b/es/css/images/final.png differ diff --git a/es/css/images/font.png b/es/css/images/font.png new file mode 100644 index 00000000000..8561bb1cb03 Binary files /dev/null and b/es/css/images/font.png differ diff --git a/es/css/images/margin2.png b/es/css/images/margin2.png new file mode 100644 index 00000000000..5ecba91ae54 Binary files /dev/null and b/es/css/images/margin2.png differ diff --git a/es/deploy/README.md b/es/deploy/README.md new file mode 100755 index 00000000000..d6c1234d88a --- /dev/null +++ b/es/deploy/README.md @@ -0,0 +1,237 @@ +# Deploy! + +> **Nota** El siguiente capítulo puede ser un poco difícil de seguir a veces. Se persistente y acábalo. El despliegue es una parte importante del proceso en el desarrollo web. Este capítulo está situado a la mitad del tutorial, de esta manera tu mentor puede ayudarte en el proceso de poner tu sitio web en línea. Esto significa que podrás acabar el tutorial por tu cuenta si se te acaba el tiempo. + +Hasta ahora tu sitio web estaba disponible sólo en tu ordenador, ahora aprenderás como desplegarlo! El despliegue es el proceso de publicar tu aplicación en internet para que la gente pueda acceder y ver tu aplicación :). + +Como ya has aprendido, un sitio web tiene que estar en un servidor. Hay un montón de proveedores, pero usaremos el que tiene el proceso de despliegue más sencillo: [Heroku][1]. Heroku es gratis para pequeñas aplicaciones que no tienen demasiadas visitas, será más que suficiente por ahora. + + [1]: http://heroku.com/ + +Seguiremos este tutorial: https://devcenter.heroku.com/articles/getting-started-with-django, pero lo hemos copiado a continuación para que sea más fácil para ti. + +## El fichero `requirements.txt` + +Necesitamos crear un fichero de requisitos `requirements.txt` para decirle a Heroku que paquetes Python necesitan ser instalados en nuestro servidor. + +Pero primero Heroku necesita que instalemos unos cuantos paquetes. Ves a tu consola con `virtualenv` activado y escribe esto: + + (myvenv) $ pip install dj-database-url waitress whitenoise + + +Cuando haya acabado la instalación, ves al directorio `djangogirls` y ejecuta el siguiente comando: + + (myvenv) $ pip freeze > requirements.txt + + +Esto creará un fichero llamado `requirements.txt` con la lista de los paquetes que tienes instalados (i.e. librerías Python que estés utilizando, por ejemplo Django :)). + +> **Nota**: `pip freeze` devuelve una lista de todas las librerías Python instaladas en tu virtualenv y `>` toma la salida de `pip freeze` y la pone en un fichero. Prueba a ejecutar `pip freeze` sin el `> requirements.txt` para ver que pasa! + +Abre este archivo y añade la siguiente línea al final: + + psycopg2==2.5.3 + + +Esta línea es necesaria para que tu aplicación funcione en Heroku. + +## Procfile + +Otra cosa que necesitamos crear es un Procfile. Eso ayudará a Heroku a saber que comandos debe ejecutar para poner en marcha nuestro sitio web. Abre tu editor de código, crea un fichero llamado `Procfile` en el directorio `djangogirls` y añade esta línea: + + web: waitress-serve --port=$PORT mysite.wsgi:application + + +Esta línea quiere decir que vamos a desplegar una aplicación `web` y para hacerlo ejecutaremos el comando `waitress-serve --port=$PORT mysite.wsgi:application` (`waitress-serve` es un programa que es como una versión más potente que el comando de Django `runserver`). + +Ahora salva los cambios. Hecho! + +## El fichero `runtime.txt` + +Tenemos que decirle a Heroku que versión de Python queremos utilizar. Esto se hace creando un fichero `runtime.txt` en el directorio `djangogirls` usando el comando de tu editor "new file" y poniendo el siguiente texto (y nada más!) en él: + + python-3.4.2 + + +## mysite/local_settings.py + +Hay diferencias entre la configuración que utilizamos en local (en nuestro ordenador) y la configuración para nuestro servidor. Heroku utiliza una base de datos y tu ordenador utiliza otra diferente. Por eso necesitamos crear ficheros separados para la configuración de nuestro entorno local. + +Crea el fichero `mysite/local_settings.py`. Debería contener la configuración de la `BASE DE DATOS` de tu fichero `mysite/settings.py`. Simplemente como esto: + + import os + BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } + + DEBUG = True + + +Ahora guarda los cambios! :) + +## mysite/settings.py + +Otra cosa que tenemos que hacer es modificar el fichero `settings.py` de nuestro sitio web. Abre `mysite/settings.py` en tu editor y añade las siguientes líneas al final del fichero: + + import dj_database_url + DATABASES['default'] = dj_database_url.config() + + SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + + ALLOWED_HOSTS = ['*'] + + STATIC_ROOT = 'staticfiles' + + DEBUG = False + + +Al final del fichero `mysite/settings.py`, copia y pega esto: + + try: + from .local_settings import * + except ImportError: + pass + + +Esto importará tu configuración local si el fichero existe. + +Ahora guarda los cambios. + +## mysite/wsgi.py + +Abre el fichero `mysite/wsgi.py` y añade estas líneas al final: + + from whitenoise.django import DjangoWhiteNoise + application = DjangoWhiteNoise(application) + + +Genial! + +## Cuenta Heroku + +Necesitas instalar Heroku toolbelt, puedes encontrarlo aquí (puedes saltarte la instalación si ya lo has instalado durante la configuración): https://toolbelt.heroku.com/ + +> Cuando estés ejecutando la instalación de Heroku toolbel en Windows asegúrate de escoger la "Instalación personalizada" cuando te pregunte por los componentes que quieres instalar. En la lista de componentes que te aparecerá, selecciona adicionalmente la casilla de "Git and SSH". +> +> En Windows también debes ejecutar el siguiente comando para añadir Git y SSH a tu ruta `PATH`: `setx PATH "%PATH%;C:\Program Files\Git\bin"`. Reinicia la consola de línea de comandos después para que los cambios se hagan efectivos. + +Por favor, crea también una cuenta gratis Heroku en: https://id.heroku.com/signup/www-home-top + +Ahora autentícate en tu cuenta de Heroku en tu ordenador ejecutando el siguiente comando: + + $ heroku login + + +En el caso de no tener una clave SSH, este comando creará una automáticamente. Las claves SSH son necesarias para subir el código a Heroku. + +## Git + +Git es un sistema de control de versiones que usan muchos programadores-software que guarda el registro de cambios en el tiempo de un fichero o un conjunto de ficheros de manera que puedes volver a una versión anterior en el futuro. Heroku utiliza un repositorio git para administrar los ficheros de tus proyectos, así que también tenemos que utilizarlo. + +Crea un fichero llamado `.gitignore` en tu directorio `djangogirls` con el siguiente contenido: + + myvenv + __pycache__ + staticfiles + local_settings.py + db.sqlite3 + + +y guarda los cambios. El punto al principio del nombre del fichero es importante! Como puedes ver, ahora le estamos diciendo a Heroku que ignore el fichero `local_settings.py` y no lo descargue, para que esté disponible solamente en tu ordenador (en local). + +A continuación crearemos un nuevo repositorio git y guardaremos nuestros cambios. Ve a la consola y ejecuta los siguientes comandos: + + $ git init + Initialized empty Git repository in ~/djangogirls/.git/ + $ git config user.name "Your Name" + $ git config user.email you@example.com + + +Solo necesitamos inicializar el repositorio git una única vez por proyecto. + +Y finalmente guardamos nuestros cambios. Ve a la consola y ejecuta estos comandos: + + $ git add -A . + $ git commit -m "My Django Girls app" + [master (root-commit) 2943412] My Django Girls + 7 files changed, 230 insertions(+) + create mode 100644 .gitignore + create mode 100644 Procfile + create mode 100644 mysite/__init__.py + create mode 100644 mysite/settings.py + create mode 100644 mysite/urls.py + create mode 100644 mysite/wsgi.py + create mode 100644 manage.py + create mode 100644 requirements.txt + create mode 100644 runtime.txt + + +## Escoge un nombre de aplicación + +Tu blog estará disponible en la Web en `[el nombre de tu blog].herokuapp.com`, así que necesitas escoger un nombre que nadie haya cogido anteriormente. Este nombre no tiene porque estar relacionado con la aplicación `blog` de Django ni con `mysite` ni con nada de lo que hemos creado anteriormente. El nombre puede ser el que tu quieras, pero Heroku es un poco estricto en cuanto a los caracteres que puedes utilizar: solo puedes usar caracteres simples en minúscula (ni mayúsculas ni acentos) números y guiones (`-`). + +Una vez hayas pensado en un nombre (quizás algo con tu nombre o tu alias), ejecuta este comando, remplazando `djangogirlsblog` con el nombre de tu aplicación: + + $ heroku create djangogirlsblog + + +> **Nota**: Recuerda que tienes que reemplazar `djangogirlsblog` con el nombre de tu aplicación en Heroku. + +Si no se te ocurre ningún nombre, puedes ejecutar + + $ heroku create + + +y Heroku escogerá un nombre para ti (probablemente algo como `enigmatic-cove-2527`). + +Si en algún momento quisieras cambiar el nombre de tu aplicación Heroku, puedes hacerlo ejecutando el siguiente comando (reemplazando `tu-nuevo-nombre` por el nuevo nombre que quieras utilizar): + + $ heroku apps:rename tu-nuevo-nombre + + +> **Nota**: Recuerda que después de haber cambiado el nombre de tu aplicación, tienes que acceder `el nuevo nombre].herokuapp.com` para ver tu sitio web. + +## Despliegue en Heroku! + +Hemos hecho un montón de configuración e instalación, verdad? Pero sólo tienes que hacer esto una única vez! Ahora ya puedes hacer el depliegue! + +Cuando ejecutaste `heroku create`, automáticamente se añadió el Heroku remoto para nuestra aplicación a nuestro repositorio. Ahora podemos hacer un simple <0>git push para desplegar nuestra aplicación: + + $ git push heroku master + + +> **Nota**: Esto probablemente producirá una salida *muy larga* la primera vez, porque Heroku compila e instala psycopg. Sabrás que todo ha ido bien si ves algo como `https://elnombre detuaplicacion.herokuapp.com/ deployed to Heroku` hacia el final de la salida. + +## Accede a tu aplicación + +Ya has desplegado tu código en Heroku y has especificado el tipo de proceso en un `Procfile` (especificamos un proces de tipo `web` anteriormente). Ahora ya podemos decirle a Heroku que inicie este `proceso web`. + +Para hacer esto, ejecuta el siguiente comando: + + $ heroku ps:scale web=1 + + +Esto le dice a Heroku que ejecute sólo una instancia de nuestro proceso `web`. Como la aplicación de nuestro blog es bastante sencilla, no necesitamos demasiado así que es suficiente ejecutar un solo proceso. Es posible decirle a Heroku que ejecute más procesos (por cierto, Heroku llama a estos procesos "Dynos" así que no te sorprendas si ves este término) pero entonces ya no será gratis. + +Ahora podemos acceder a la aplicación en nuestro navegador con `heroku open`. + + $ heroku open + + +> **Nota**: Verás una página de error! Hablaremos de esto en seguida + +Esto abrirá una url como [https://djangogirlsblog.herokuapp.com/]() en tu navegador y probablemente verás una página de error. Como de momento sólo hemos creado la vista de administración para la aplicación, añade `admin/` a la url (i.e. [https://djangogirlsblog.herokuapp.com/admin/]()) para poder ver una versión de tu aplicación web funcionando. + +El error que veías era debido a que cuando desplegamos en Heroku creamos una nueva base de dados y ésta está vacía. Necesitamos ejecutar el comando ~~~ migrate~~~ como hicimos cuando empezamos nuestro proyecto para configurar nuestra base de datos correctamente: + + $ heroku run python manage.py migrate + + $ heroku run python manage.py createsuperuser + + +Ahora deberías poder acceder a tu sitio web desde el navegador! Felicidades :)! \ No newline at end of file diff --git a/es/django/README.md b/es/django/README.md new file mode 100755 index 00000000000..597c81a2f28 --- /dev/null +++ b/es/django/README.md @@ -0,0 +1,27 @@ +# ¿Qué es Django? + +Django (*gdh/ˈdʒæŋɡoʊ/jang-goh*) es un framework para aplicaciones web gratuito y open source, escrito en Python. Es un WEB framework - un conjunto de componentes que te ayudan a desarrollar sitios web más fácil y rápidamente. + +Verás, cuando estás construyendo un sitio web, frecuentemente necesitas componentes similares: autenticación de usuario (iniciar sesion, cerrar sesion, registrarse), un panel de administración para su sitio web, formularios, una forma de subir archivos, etc. + +Por suerte para ti, hace tiempo varias personas notaron que los desarrolladores web enfrentan problemas similares cuando construyen un sitio nuevo, por eso juntaron cabezas y crearon frameworks (Django es uno de ellos) que te ofrecen componentes listos para usarse. + +Los frameworks existen para ahorrarte tener que reinventar la rueda y ayudarte a aliviar la carga cuando construyes un sitio. + +## ¿Por qué necesitas un framework? + +Para entender para que es Django, necesitamos mirar mas de cerca a los servidores. Lo primero es que el servidor necesita saber que quieres que te sirva una página web. + +Imagina un buzón (puerto) el cual es monitoreado por cartas entrantes (peticiones). Esto es realizado por un servidor web. El servidor web lee la carta, y envía una respuesta con una página web. Pero cuando quieres enviar algo, tienes que tener algún contenido. Y Django es algo que te ayuda a crear el contenido. + +## ¿Qué sucede cuando alguien solicita una página web de tu servidor? + +Cuando llega una petición a un servidor web es pasado a Django que intenta averiguar lo que realmente es solicitado. Toma primero una dirección de página web y trata de averiguar qué hacer. Esta parte es realizada por **urlresolver** de Django (tenga en cuenta que la dirección de un sitio web es llamada URL - Uniform Resource Locator - así que el nombre *urlresolver* tiene sentido). Este no es muy inteligente - toma una lista de patrones y trata de igualar la URL. Django comprueba los patrones de arriba hacia abajo y si algo se coincide entonces Django le pasa la solicitud a la función asociada (que se llama *vista*). + +Imagina a un cartero con una carta. Ella está caminando por la calle y comprueba cada número de casa contra el que está en la carta. Si coincide, ella pone la carta ahí. Así es como funciona el urlresolver! + +En la función de *vista* se hacen todas las cosas interesantes: podemos mirar a una base de datos para buscar alguna información. ¿Tal vez el usuario pidió cambiar algo en los datos? Como una carta diciendo "Por favor cambia la descripción de mi trabajo." La *vista* puede comprobar si tenes permitido hacer eso, entonces actualizar la descripción del trabajo para usted y devolverle un mensaje: "¡hecho!". Entonces la *vista* genera una respuesta y Django puede enviarla al navegador del usuario. + +Por supuesto, la descripción anterior se simplifica un poco, pero no necesitas saber todas las cosas técnicas aun. Tener una idea general es suficiente. + +Así que en lugar de meternos demasiado en los detalles, simplemente comenzaremos creando algo con Django y aprenderemos todas las piezas importantes en el camino! \ No newline at end of file diff --git a/es/django_admin/README.md b/es/django_admin/README.md new file mode 100755 index 00000000000..b4211bd63cc --- /dev/null +++ b/es/django_admin/README.md @@ -0,0 +1,52 @@ +# Administrador de Django + +Para agregar, editar y borrar los mensajes que hemos modelamos, utilizaremos el administrador de Django. + +Vamos a abrir el archivo `blog/admin.py` y reemplazar su contenido con esto: + + from django.contrib import admin + from .models import Post + + admin.site.register(Post) + + +Como puedes ver, importamos (incluimos) el modelo Post definido en el capítulo anterior. Para hacer nuestro modelo visible en la página del administrador, tenemos que registrar el modelo con `admin.site.register(Post)`. + +Es hora de mirar a nuestro modelo de Post. Recuerde que debe ejecutar `python manage.py runserver` en la consola para ejecutar el servidor web. Vaya al navegador y escriba la dirección: + + http://127.0.0.1:8000/admin/ + + +Usted verá una página de inicio de sesión como esta: + +![Página de inicio de sesión][1] + + [1]: images/login_page2.png + +Para poder entrar necesitas crear un *superusuario* - un usuario que tiene control sobre todo en el sitio. Vuelve a la línea de comandos y escribe `python manage.py createsuperuser`, presione enter y escriba su nombre de usuario (en minúscula, sin espacios), dirección de correo electrónico y contraseña cuando te pregunten por ellos. La salida debe ser así (donde nombre de usuario y correo electrónico deben ser los tuyos): + + (myvenv) ~/djangogirls$ python manage.py createsuperuser + Username: admin + Email address: admin@admin.com + Password: + Password (again): + Superuser created successfully. + + +Regresa a tu navegador e inicia sesión con las credenciales de superusuario que elegiste, deberías ver el tablero de administración de Django. + +![Administrador de Django][2] + + [2]: images/django_admin3.png + +Ve a Posts y experimentar un poco con él. Agrega cinco o seis entradas en el blog. No te preocupes por el contenido - puedes simplemente copiar y pegar algún texto de este tutorial como contenido de tus mensajes para ahorrar tiempo :). + +Asegúrate que al menos dos o tres entradas (pero no todas) tengan la fecha de publicación. Será de ayuda más tarde. + +![Administrador de Django][3] + + [3]: images/edit_post3.png + +Sí quieres sabes más sobre Django admin, deberías revisar la documentación de Django: https://docs.djangoproject.com/en/1.7/ref/contrib/admin/ + +Probablemente sea un buen momento para tomar un café (o té) y comer algo dulce. Haz creado tu primer modelo Django - te mereces un regalito! \ No newline at end of file diff --git a/es/django_admin/images/django_admin3.png b/es/django_admin/images/django_admin3.png new file mode 100644 index 00000000000..a450b4f9630 Binary files /dev/null and b/es/django_admin/images/django_admin3.png differ diff --git a/es/django_admin/images/edit_post3.png b/es/django_admin/images/edit_post3.png new file mode 100644 index 00000000000..c8572a73e7d Binary files /dev/null and b/es/django_admin/images/edit_post3.png differ diff --git a/es/django_admin/images/login_page2.png b/es/django_admin/images/login_page2.png new file mode 100644 index 00000000000..47153ef6960 Binary files /dev/null and b/es/django_admin/images/login_page2.png differ diff --git a/es/django_forms/README.md b/es/django_forms/README.md new file mode 100755 index 00000000000..66527b22950 --- /dev/null +++ b/es/django_forms/README.md @@ -0,0 +1,334 @@ +# Formularios en Django + +Por último, queremos crear un apartado en nuestra web para poder agregar y editar entradas en el blog. Django `admin` está bien, pero es bastante difícil de personalizar y hacerlo bonito. Con `forms` tendremos un poder absoluto sobre nuestra interfaz - podemos hacer casi cualquier cosa que podamos imaginar! + +Lo bueno de Django forms es que podemos definirlo desde cero o creando un `ModelForm` y se guardará el resultado del formulario en el modelo. + +Esto es exactamente lo que queremos hacer: crearemos un formulario para nuestro modelo `Post`. + +Como cada parte importante de Django, forms tienen su propio archivo: `forms.py`. + +Tenemos que crear un archivo con este nombre en el directorio `blog`. + + blog + └── forms.py + + +Ok, vamos abrirlo y vamos a escribir el siguiente código: + + from django import forms + + from .models import Post + + class PostForm(forms.ModelForm): + + class Meta: + model = Post + fields = ('title', 'text',) + + +Primero necesitamos importar Django forms (`from django import forms`) y, obviamente, nuestro modelo de `Post` (`from .models import Post`). + +`PostForm`, como probablemente sospechas, es el nombre del formulario. Necesitamos decirle a Django que este formulario es un `ModelForm` (así Django hará algo de magia para nosotros) - `forms.ModelForm` es responsable de ello. + +A continuación, tenemos `class Meta`, donde le decimos a Django que modelo debe utilizar para crear este formulario (`model = Post`). + +Finalmente, podemos decir que campo(s) que campos queremos en nuestro formulario. En este escenario sólo queremos `título` y `texto` - `autor` será la persona que se ha autenticado (tú!) y `fecha_de_creacion` se definirá automáticamente cuando creemos una entrada (es decir en el código), ¿si? + +Y eso es todo! Todo lo que necesitamos hacer ahora es usar el formulario en una *view* y mostrarla en una plantilla. + +Una vez más vamos a crear: un enlace a la página, una dirección URL, una vista y una plantilla. + +## Enlace a una página con el formulario + +Es hora de abrir `blog/templates/blog/base.html`. Vamos a añadir un enlace en `div` llamado `encabezado de página`: + + < a href = "{url 'blog.views.post_new' %}" class = "top-menu" >< span class = "glyphicon glyphicon-plus" >< / span >< /a > + + +Ten en cuenta que queremos llamar a nuestra nueva vista `post_new`. + +Después de agregar la línea, tu archivo html debería tener este aspecto: + + {% load staticfiles %} + + + Django Girls blog + + + + + + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + + + +Después de guardar y actualizar la página `http://127.0.0.1:8000` obviamente podrá ver un error de `NoReverseMatch` familiar, ¿verdad? + +## URL + +Abrimos el `blog/urls.py` y añadimos una línea: + + url(r'^post/new/$', views.post_new, name='post_new'), + + +Y el código final tendrá este aspecto: + + from django.conf.urls import patterns, include, url + from . import views + + urlpatterns = patterns('', + url(r'^$', views.post_list), + url(r'^post/(?P[0-9]+)/$', views.post_detail), + url(r'^post/new/$', views.post_new, name='post_new'), + ) + + +Después de actualizar el sitio, veremos un `AttributeError`, puesto que no tenemos la vista `post_new` implementado. Vamos a añadir ahora. + +## vista post_new + +Es el momento de abrir el archivo `blog/views.py` y agregar las siguientes líneas al resto de las filas `from`: + + from .forms import PostForm + + +y nuestra *vista*: + + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) + + +Para crear un nuevo formulario `Post`, tenemos que llamar a `PostForm()` y pasar a la plantilla. Volveremos a esta *vista*, pero por ahora, vamos a crear rápidamente una plantilla para el formulario. + +## Plantilla + +Tenemos que crear un archivo `post_edit.html` en el directorio `blog/plantillas/blog`. Para hacer que un formulario funcione necesitamos varias cosas: + +* Tenemos que mostrar el formulario. Podemos hacerlo por ejemplo con un simple `{{ form.as_p }}`. +* la línea anterior tiene que estar dentro de una etiqueta de formulario HTML: `< form method = "POST" >... < / form >` +* Necesitamos un botón `Guardar`. Lo hacemos con un botón HTML: `< button type = 'submit' > guardar < / button >` +* y finalmente justo después de la apertura de `< form... >` necesitamos agregar `{% csrf_token %}`. Esto es muy importante, ya que hace que tus formularios sean seguros! Django se quejará si te olvidas de esta parte cuando intente guardar el formulario: + +![CSFR prohibida][1] + + [1]: images/csrf2.png + +Bueno, vamos a ver cómo quedará el HTML en `post_edit.html`: + + {% extends 'blog/base.html' %} + + {% block content %} +

New post

+
{% csrf_token %} + {{ form.as_p }} + +
+ {% endblock %} + + +Es hora de actualizar! ¡ Si! El formulario se muestra! + +![Nuevo formulario][2] + + [2]: images/new_form2.png + +Pero, ¡ un momento! Si escribes algo en los campos `título` y `texto` y tratas de salvar-¿qué pasa? + +¡ Nada! Una vez más estamos en la misma página y el texto se ha ido... no se añade ningún mensaje nuevo. Entonces, ¿qué ha ido mal? + +La respuesta es: nada. Tenemos que trabajar un poco más en nuestra *vista*. + +## Guardar el formulario + +Abre `blog/views.py` una vez más. De momento todo lo que tenemos en la vista `post_new` es: + + def post_new(request): + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) + + +Cuando enviamos el formulario, estamos en la misma vista, pero esta vez tenemos algunos datos más en la `request`, concretamente en `request.POST`. ¿Recuerdas que en el archivo HTML la definición de `< form >` tenía la variable `method = "POST"`? Todos los campos del formulario estan ahora en `request.POST`. No deberías renombrar la variable `POST` (el único nombre que también es válido para la variable `method` es `GET`, pero no tenemos tiempo para explicar cuál es la diferencia). + +En nuestra *vista* tenemos dos posibles situaciones a contemplar. Primera: cuando accedemos a la página por primera vez y queremos un formulario en blanco. Segundo: cuando volvemos a la *vista* con los datos del formulario que acabamos de escribir. Así que tenemos que añadir una condición (utilizaremos `if` para eso). + + if request.method == "POST": + [...] + else: + form = PostForm() + + +Es hora de llenar los puntos `[...]`. Si el `method` es `POST` queremos construir el `PostForm` con los datos del formulario, ¿no? Lo haremos con: + + form = PostForm(request.POST) + + +Fácil! Lo siguiente es verificar si el formulario es correcto (todos los campos necesarios están definidos y no hay valores incorrectos). Lo hacemos con `form.is_valid()`. + +Comprobamos que el formulario es válido y si es así, lo podemos salvar. + + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.save() + + +Básicamente, tenemos que hacer dos cosas aquí: salvar el formulario con `form.save` y añadirle un autor (ya que no había ningún campo de `autor` en el `PostForm` y este campo es obligatorio). `cometer = False` significa que no queremos guardar el modelo `Post` todavía - queremos añadir el autor primero. La mayoría de las veces utilizarás `form.save()`, sin `commit = False`, pero en este caso, tenemos que hacerlo. `post.Save()` conservará los cambios (añadiendo a autor) y se creará una nueva entrada en el blog! + +Por último, sería genial si podemos inmediatamente ir a la página `post_detail` de la entrada de blog que se acaba de crear, ¿no? Para hacerlo necesitamos una importación más: + + from django.shortcuts import redirect + + +Añádelo al principio del archivo. Y ahora podemos decir: ves a la página `post_detail` de la entrada recién creada. + + return redirect('blog.views.post_detail', pk=post.pk) + + +`blog.views.post_detail` es el nombre de la vista a la que queremos ir. ¿Recuerdas que esta *vista* requiere una variable `pk`? Para pasarlo a las vistas utilizamos `pk=post.pk`, donde `post` es la entrada recién creada! + +Bien, hablamos mucho, pero probablemente queremos ver como es ahora la *vista*, verdad? + + def post_new(request): + if request.method == "POST": + form = PostForm(request.POST) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm() + return render(request, 'blog/post_edit.html', {'form': form}) + + +Vamos a ver si funciona. Ves a la página `http://127.0.0.1:8000/post/new/`, añadir un `título` y un `texto`, guárdalo... ¡ y voilá! Se añade la nueva entrada al blog y se nos redirige a la página de `post_detail`! + +Probablemente has visto que no hemos definido la fecha de publicación. Vamos a introducir un *botón publicar* en **Django girls Tutorial: extensiones**. + +Eso es impresionante! + +## Validación de formularios + +Ahora, vamos a enseñarte cómo mola Django forms. Un blog debe tener `título` y `texto`. En nuestro modelo `Post` no dijimos (a diferencia de `published_date`) que estos campos son requeridos, así que Django, por defecto, espera ellos. + +Trata de guardar el formulario sin `title` y `text`. Adivina, qué pasará! + +![Validación de formularios][3] + + [3]: images/form_validation2.png + +Django es cuidadoso de validar que todos los campos en el formulario estén correctos. ¿No es genial? + +> Como recientemente hemos utilizado la interfaz de administrador de Django, el sistema piensa que estamos logueados. Hay algunas situaciones que podrían llevarnos a quedar como no registrados (cerrando el navegador, reiniciando la base de datos etc.). Si estás recibiendo errores al crear un post que indican la falta de inicio de sesión de usuario, dirígete a la pagina de admin `http://127.0.0.1:8000/admin` e inicia sesión nuevamente. Esto resolverá el problema temporalmente. Hay un arreglo permanente en el capítulo **Tarea: ¡Añadir seguridad a tu sitio web!** después del tutorial principal. + +![Error de inicio de sesión][4] + + [4]: images/post_create_error.png + +## Editar formulario + +Ahora sabemos cómo agregar un nuevo formulario. Pero ¿qué pasa si queremos editar uno existente? Es muy similar a lo que hicimos anteriormente. Vamos a crear algunas cosas importantes rápidamente. (si no entiendes algo, pregúntalo a tu tutor o revisa lo capítulos anteriores, son temas que ya hemos cubierto). + +Abre el archivo `blog/templates/blog/post_detail.html` y añade esta línea: + + + + +para que la plantilla quede: + + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} + {{ post.published_date }} + {% endif %} + +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+ {% endblock %} + + +En el archivo `blog/urls.py` añadimos esta línea: + + url(r'^post/(?P[0-9]+)/edit/$', views.post_edit, name='post_edit'), + + +Vamos a reusar la plantilla `blog/templates/blog/post_edit.html`, así que lo último que nos falta es una *view*. + +Abramos el archivo `blog/views.py` y añadamos al final esta línea: + + def post_edit(request, pk): + post = get_object_or_404(Post, pk=pk) + if request.method == "POST": + form = PostForm(request.POST, instance=post) + if form.is_valid(): + post = form.save(commit=False) + post.author = request.user + post.save() + return redirect('blog.views.post_detail', pk=post.pk) + else: + form = PostForm(instance=post) + return render(request, 'blog/post_edit.html', {'form': form}) + + +Esto se ve casi exactamente igual a nuestra view `post_new`, ¿no? Pero no del todo. Primero: pasamos un parámetro extra `pk` de los urls. Luego: obtenemos el modelo `Post` que queremos editar con `get_object_or_404(Post, pk=pk)` y después, al crear el formulario pasamos este post como una `instancia` tanto al guardar el formulario: + + form = PostForm(request.POST, instance=post) + + +como al abrir un formulario con este post para editarlo: + + form = PostForm(instance=post) + + +Ok, ¡vamos a probar si funciona! Dirígete a la página `post_detail`. Debe haber ahí un botón para editar en la esquina superior derecha: + +![Botón Editar][5] + + [5]: images/edit_button2.png + +Al dar click ahí, debes ver el formulario con nuestro post del blog: + +![Editar formulario][6] + + [6]: images/edit_form2.png + +¡Siéntete libre de cambiar el título o el texto y guarda los cambios! + +¡Felicitaciones.Tu aplicación está cada vez más completa! + +Si necesitas más información sobre los formularios de Django, debes leer la documentación: https://docs.djangoproject.com/en/1.7/topics/forms/ + +## Una cosa más: ¡Tiempo de implementación! + +Sería bueno ver si tu sitio sigue funcionando en Heroku, ¿no? Intentemos implementarlo nuevamente. Si olvidaste como hacerlo, revisa el final del capítulo 15: + + $ git status + ... + $ git add -A . + $ git status + ... + $ git commit -m "Added views to create/edit blog post inside the site." + ... + $ git push heroku master + + +¡Y eso debería ser todo! Felicidades :) \ No newline at end of file diff --git a/es/django_forms/images/csrf2.png b/es/django_forms/images/csrf2.png new file mode 100644 index 00000000000..9dd1a9a4baa Binary files /dev/null and b/es/django_forms/images/csrf2.png differ diff --git a/es/django_forms/images/drafts.png b/es/django_forms/images/drafts.png new file mode 100644 index 00000000000..f984ec2a4ae Binary files /dev/null and b/es/django_forms/images/drafts.png differ diff --git a/es/django_forms/images/edit_button2.png b/es/django_forms/images/edit_button2.png new file mode 100644 index 00000000000..f402eadd00b Binary files /dev/null and b/es/django_forms/images/edit_button2.png differ diff --git a/es/django_forms/images/edit_form2.png b/es/django_forms/images/edit_form2.png new file mode 100644 index 00000000000..329674ee5ad Binary files /dev/null and b/es/django_forms/images/edit_form2.png differ diff --git a/es/django_forms/images/form_validation2.png b/es/django_forms/images/form_validation2.png new file mode 100644 index 00000000000..0e81288c33e Binary files /dev/null and b/es/django_forms/images/form_validation2.png differ diff --git a/es/django_forms/images/new_form2.png b/es/django_forms/images/new_form2.png new file mode 100644 index 00000000000..8180ce66a06 Binary files /dev/null and b/es/django_forms/images/new_form2.png differ diff --git a/es/django_forms/images/post_create_error.png b/es/django_forms/images/post_create_error.png new file mode 100644 index 00000000000..ae4650a575a Binary files /dev/null and b/es/django_forms/images/post_create_error.png differ diff --git a/es/django_installation/README.md b/es/django_installation/README.md new file mode 100755 index 00000000000..85b5705d85f --- /dev/null +++ b/es/django_installation/README.md @@ -0,0 +1,113 @@ +# Instalacion de Django + +> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (http://django.carrots.pl/). +> +> Parte de este capítulo se basa en el [tutorial de django-marcador][1] bajo licencia de Creative Commons Attribution-ShareAlike 4.0 internacional. El tutorial de django-marcador tiene derechos de autor de Markus Zapke-Gündemann et al. + + [1]: http://django-marcador.keimlink.de/ + +## Entorno virtual + +Antes de instalar Django, instalaremos una herramienta extremadamente útil que ayudará a mantener tu entorno de desarrollo ordenado en su computadora. Es posible omitir este paso, pero es muy recomendable no hacerlo, comenzar con la mejor configuración posible ayudara a evitar muchos problemas en el futuro! + +Así que, vamos a crear un **entorno virtual** (también llamado un *virtualenv*). Aislará la configuración Python/Django en base de cada proyecto, lo que significa que cualquier cambio que realice en un sitio web no afectará a otros que también está desarrollando. Genial, no? + +Todo lo que necesita hacer es encontrar un directorio en el que desea crear el `virtualenv`; su directorio home, por ejemplo. En Windows puede parecer como `C:\Users\Name` (donde `nombre` es el nombre de tu login). + +Para este tutorial usaremos un nuevo directorio `djangogirls` de tu directorio home: + + mkdir djangogirls + cd djangogirls + + +Haremos un virtualenv llamado `myvenv`. El comando general estará en el formato: + + python -m venv myvenv + + +### Windows + +Para crear un nuevo `virtualenv`, debes abrir la consola (te lo indicamos unos cuantos capítulos antes, ¿recuerdas?) y ejecuta `C:\Python34\python -m venv myvenv`. Se verá así: + + C:\Users\Name\djangogirls> C:\Python34\python -m venv myvenv + + +en donde `C:\Python34\python` es el directorio en donde instalaste Python previamente y `myvenv` es el nombre de tu `virtualenv`. Puedes usar cualquier otro nombre, pero mantén el uso de minúsculas y no incluyas espacios. También es una buena idea mantener el nombre corto. ¡Vas a referirte a él mucho! + +### Linux and OS X + +Crear un `virtualenv` en Linux y OS X es tan simple como ejecutar `python3 -m venv myvenv`. Se verá así: + + ~/djangogirls$ python3 -m venv myvenv + + +`myvenv` es el nombre de tu `virtualenv`. Puedes usar cualquier otro nombre, pero mantén el uso de minúsculas y no incluyas espacios. También es una buena idea mantener el nombre corto. ¡Vas a referirte a él mucho! + +> **NOTA:** Iniciar el entorno virtual en Ubuntu 14.04 de esta manera, actualmente produce el siguiente error: +> +> Error: Command '['/home/eddie/Slask/tmp/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1 +> +> +> Para evitar esto, utilice el comando `virtualenv`. +> +> ~/djangogirls$ sudo apt-get install python-virtualenv +> ~/djangogirls$ virtualenv --python=python3.4 myvenv +> + +## Trabajar con virtualenv + +Este comando anterior creará un directorio llamado `myvenv` (o cualquier nombre que hayas escogido) que contiene nuestro entorno virtual (básicamente un montón de archivos y carpetas). Todo lo que queremos hacer ahora es iniciarlo ejecutando: + + C:\Users\Name\djangogirls> myvenv\Scripts\activate + + +en Windows, o: + + ~/djangogirls$ source myvenv/bin/activate + + +en OS X y Linux. + +¡Recuerda reemplazar `myvenv` con tu nombre de `virtualenv` que hayas elegido! + +> **Nota:** a veces la `fuente` podría no estar disponible. En esos casos trata de hacerlo esto: +> +> ~/djangogirls$ . myvenv/bin/activate +> + +Sabrás que tienes `virtualenv` iniciado cuando veas que parece este mensaje en la consola: + + (myvenv) C:\Users\Name\djangogirls> + + +o: + + (myvenv) ~/djangogirls$ + + +¡Nota que el prefijo `(myvenv)` aparece! + +Cuando trabajes en un entorno virtual, `python` automáticamente se referirá a la versión correcta, de modo que puedes utilizar `python` en vez de `python3`. + +Tenemos todas las dependencias importantes en su lugar. ¡Finalmente podemos instalar Django! + +## Instalar Django + +Ahora que tienes tu `virtualenv` iniciado, puedes instalar Django usando `pip`. En la consola, ejecuta `pip install django == 1.7.1` (fíjate que utilizamos un doble signo igual): `==`). + + (myvenv) ~$ pip install django==1.7.1 + Downloading/unpacking django==1.7.1 + Installing collected packages: django + Successfully installed django + Cleaning up... + + +En Windows + +> Si se obtiene un error al llamar a pip en Windows, comprueba si la ruta a tu proyecto contiene espacios (es decir, `C:\Users\User Name\djangogirls`). Si es así, por favor considera moverla a otro lugar sin espacios (sugerencia: `C:\djangogirls`). Después de hacerlo ejecuta nuevamente el comando anterior. + +en Linux + +> Si obtienes un error al correr pip en Ubuntu 12.04 ejecuta `python -m pip install- U - force-resintall pip` para arreglar la instalación de pip en el virtualenv. + +¡Eso es todo. Ahora estás listo (por fin) para crear una aplicación Django! Pero para hacer eso, necesitas un buen programa en el cual escribir código... \ No newline at end of file diff --git a/es/django_models/README.md b/es/django_models/README.md new file mode 100755 index 00000000000..b6efa40d3fc --- /dev/null +++ b/es/django_models/README.md @@ -0,0 +1,173 @@ +# Modelos en Django + +Lo que queremos crear ahora es algo que va a almacenar todas las entradas en nuestro blog. Pero para poder hacerlo tenemos que hablar un poco de acerca de algo llamado `objetos`. + +## Objetos + +Hay un concepto en el mundo de la programación llamado `programación orientada a objetos`. La idea es que en lugar de escribir todo como una aburrida secuencia de instrucciones de programación podemos modelar cosas y definir cómo interactúan con las demás. + +Entonces ¿Qué es un objeto? Es un conjunto de propiedades y acciones. Suena raro, pero te daremos un ejemplo. + +Si queremos un modelar un gato crearemos un objeto `Gato` que tiene algunas propiedades, como son, `color`, `edad`, `estado de ánimo` (es decir, bueno, malo, sueño ;)), `dueño` (que es un objeto `persona` o tal vez, en el caso de que el gato sea callejero, esta propiedad estara vacía). + +Y luego el `Gato` tiene algunas acciones: `ronronear`, `rasguñar` o `alimentarse` (en la cual daremos el gato algunos `ComidaDeGato`, que podría ser un objeto independiente con propiedades, como por ejemplo, `sabor`). + + Gato + --------- + color + edad + humor + dueño + ronronear() + rasguñar() + alimientarse(comida_de_gato) + + ComidaDeGato + ---------- + sabor + + +Básicamente se trata de describir cosas reales en el código con propiedades (llamadas `Propiedades del objeto`) y las acciones (llamadas `métodos`). + +y ahora ¿Cómo modelamos las entradas en el blog? Queremos construir un blog, ¿no? + +Tenemos primero que responder algunas preguntas: ¿Qué es una entrada de un blog? ¿Qué características debe tener? + +Bueno, seguro que nuestras entradas necesitan un texto con su contenido y un título, ¿Cierto? También sería bueno saber quién lo escribió, así que necesitamos un autor. Por último, queremos saber cuando fue creado y publicado dicha entrada. + + Entrada + --------- + + título + texto + autor + fecha_creacion + fecha_publicacion + + +¿Qué tipo de cosas podría hacerse con una entrada del blog? Sería bueno tener algún `método` que publique la entrada, ¿no? + +Así que vamos a necesitar el método `publicar`. + +Puesto que ya sabemos lo que queremos hacer, podemos empezar a crear nuestro Modelo en Django! + +## Modelo en Django + +Sabiendo que es un objeto, podemos crear un modelo en Django para nuestras entradas en el Blog. + +Un modelo en Django es un tipo especial de objeto, que se guarda en la `base de datos`. Una base de datos es un conjunto de datos. Allí es el lugar en el cual almacenarás la información sobre usuarios, entradas del blogs, etc. Utilizaremos una base de datos SQLite para almacenar nuestros datos. Este es el adaptador de base de datos predeterminada en Django -- será suficiente para nosotros por ahora. + +Piensa en el modelo como una hoja de cálculo con columnas (campos) y filas (datos). + +### Creando una aplicación + +Para mantener todo en orden, crearemos una aplicación separada dentro de nuestro proyecto. Es muy bueno tener todo organizado desde el principio. Para crear una aplicación necesitamos ejecutar el siguiente comando en la consola (dentro `djangogirls` donde está el archivo `manage.py`): + + (myvenv) ~/djangogirls$ python manage.py startapp blog + + +Vas notar que se crea un nuevo directorio llamado `blog` y contiene una serie de archivos. Nuestros directorios y archivos en nuestro proyecto deberían parecerse a esto: + + djangogirls + ├── mysite + | __init__.py + | settings.py + | urls.py + | wsgi.py + ├── manage.py + └── blog + ├── migrations + | __init__.py + ├── __init__.py + ├── admin.py + ├── models.py + ├── tests.py + └── views.py + + +Después de crear una aplicación también necesitamos decirle a Django que debe utilizarla. Lo hacemos en el archivo `mysite/settings.py`. Tenemos que encontrar `INSTALLED_APPS` y añadir una línea que contiene `'blog',` justo por encima de `)`. El producto final debe tener este aspecto: + + INSTALLED_APPS = ( + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'blog', + ) + + +### Creando el Modelo post + +En el archivo `blog/models.py` definimos todos los objetos llamados `Models` - este es un lugar en el cual definiremos nuestro modelo post. + +Vamos abrir `blog/models.py`, quitamos todo y escribimos un código como este: + + from django.db import models + from django.utils import timezone + + class Post(models.Model): + author = models.ForeignKey('auth.User') + title = models.CharField(max_length=200) + text = models.TextField() + created_date = models.DateTimeField( + default=timezone.now) + published_date = models.DateTimeField( + blank=True, null=True) + + def publish(self): + self.published_date = timezone.now() + self.save() + + def __str__(self): + return self.title + + +> Vuelva a verificar que usaste dos caracteres undescore (`_`) en cada lado del `str`. Los que se utilizan con frecuencia en Python y a veces también los llamamos "dunder" (diminutivo de "doble-subrayado"). + +Es aterrador, ¿cierto? Pero no te preocupes, vamos a explicar qué significan estas líneas! + +Todas las líneas a partir `from` o de `import` son líneas para añadir algo de otros archivos. Así que en vez de copiar y pegar las mismas cosas en cada archivo, podemos incluir algunas partes con `from... import ...`. + +`class Post(models.Model):` - esta linea define nuestro modelo (es un `objeto`). + +* `class` Es una palabra clave que indica que estamos definiedo un objeto. +* `Post` Es el nombre de nuestro modelo, podemos darle un nombre diferente(pero debemos evitar espacios en blanco y caracteres especiales). Una clase siempre comienza con su primera letra en mayúscula. +* `models.Model` Significa que Post es un modelo de Django, así Django sabe que debe guardarlo en la base de datos. + +Ahora definimos las propiedades que hablábamos: `title`, `text`, `created_date`, `published_date` y `author`. Para hacer eso tenemos que definir un tipo de campo (¿es texto? ¿Un número? ¿Una fecha? Una relación con otro objeto, es decir, un usuario?). + +* `models.CharField` - esto es como defines un texto con un numero limitado de caracteres. +* `modelos.TextField`-esto es para textos largos sin un límite. ¿Será ideal para un blog post contenido, verdad? +* `models.DateTimeField` - esta es la fecha y hora. +* `modelos.ForeignKey`-este es una relación a otro modelo. + +No vamos a explicar cada pedacito de código, ya que nos tomaría demasiado tiempo. Debes echar un vistazo a la documentación de Django. Si quieres saber más sobre los campos de Modelos y cómo definir cosas diferentes a las descritas anteriormente (https://docs.djangoproject.com/en/1.7/ref/models/fields/#field-types). + +¿Y qué sobre `def publish(self):`? Es exactamenteel método `publish` del que hablábamos antes. `def` significa que se trata de una función o método. `publish` es el nombre del método. Puedes cambiarlo, si quieres. La regla es que usamos minúscula y guiones bajos en lugar de espacios (es decir, si quieres tener un método que calcule el precio medio, este podría llamarse `calculate_average_price`). + +Los métodos muy a menudo `devuelven` algo. Hay un ejemplo de esto en el método `__str__`. En este escenario, cuando llamamos a `__str__()` obtendremos un texto (**string**) con un título de Post. + +Si algo todavía no está claro sobre modelos, ¡no dudes en preguntar a tu tutor! Sabemos que es muy complicado, sobre todo cuando estás entendiendo qué funciones y objetos son mientras sigues este documento. Con suerte, ¡todo tiene un poco más sentido para ti ahora! + +### Crear tablas para los modelos en tu base de datos + +El último paso es añadir nuestro nuevo modelo a nuestra base de datos. Primero tenemos que hacer Django sepa que tenemos algunos cambios en nuestro modelo (acabamos de crearlo), escribe `python manage.py makemigrations blog`. Se verá así: + + (myvenv) ~/djangogirls$ python manage.py makemigrations blog + Migrations for 'blog': + 0001_initial.py: + - Create model Post + + +Django nos prepara un archivo de migración que tenemos que aplicar ahora a nuestra base de datos, escribe `python manage.py migrate blog`, el resultado debe ser: + + (myvenv) ~/djangogirls$ python manage.py migrate blog + Operations to perform: + Apply all migrations: blog + Running migrations: + Applying blog.0001_initial... OK + + +¡ Hurra! Nuestro modelo de Post está ahora en nuestra base de datos, sería bueno verlo, ¿no? Dirígete al siguiente capítulo para ver cómo luce tu Post! \ No newline at end of file diff --git a/es/django_orm/README.md b/es/django_orm/README.md new file mode 100755 index 00000000000..ae892fd207c --- /dev/null +++ b/es/django_orm/README.md @@ -0,0 +1,158 @@ +# ORM de Django y QuerySets + +En este capítulo aprenderás cómo Django se conecta a la base de datos y almacena los datos en ella. ¡Vamos a sumergirnos! + +## ¿Qué es un QuerySet? + +Un QuerySet es, en esencia, una lista de objetos de un modelo determinado. Un QuerySet te permite leer los datos de base de datos, filtrarlos y ordenarlos. + +Es más fácil de aprender con ejemplos. Vamos a intentarlo, ¿de acuerdo? + +## Django shell + +Abre la consola y escribe este comando: + + (myvenv) ~/djangogirls$ python manage.py shell + + +El resultado debería ser: + + (InteractiveConsole) + >>> + + +Ahora estás en la consola interactiva de Django. Es como la consola de Python, pero con un toque de magia Django :). Puedes utilizar todos los comandos Python aquí también, por supuesto. + +### Ver todos los objetos + +Vamos a mostrar todos nuestros objetos Posts primero. Puedes hacerlo con el siguiente comando: + + >>> Post.objects.all() + Traceback (most recent call last): + File "", line 1, in + NameError: name 'Post' is not defined + + +¡ Uy! Apareció un error. Nos dice que no hay ningún objeto Post. Esto es correcto, nos olvidamos de importarlo primero! + + >>> from blog.models import Post + + +Esto es simple: importamos el modelo `Post` de `blog.models`. Vamos a intentar mostrar todos los Posts nuevamente: + + >>> Post.objects.all() + [] + + +Es una lista vacía. Esto es correcto, ¿verdad?¡Todavía no hemos añadido ningún Post! Vamos a arreglarlo. + +### Crear objetos + +Esta es la forma de crear un objeto Post en la base de datos: + + >>> Post.objects.create(author=me, title='Sample title', text='Test') + + +Pero hay un ingrediente faltante: `me`. Necesitamos pasar una instancia del modelo `User` como autor. ¿Cómo hacemos eso? + +Primero importemos el modelo User: + + >>> from django.contrib.auth.models import User + + +¿Qué usuarios tenemos en nuestra base de datos? Veamos: + + >>> User.objects.all() + [] + + +¡Ninguno! Creemos un usuario: + + >>> User.objects.create(username='ola') + + + +Veamos nuevamente qué usuarios tenemos: + + >>> User.objects.all() + [] + + +¡ Genial! Ahora usemos una instancia del usuario: + + me = User.objects.get(username='ola') + + +Como puedes ver, ahora `get` un `User` con un `username` que es igual a 'ola'. Limpio! Por supuesto, tienes que ajustarlo a tu nombre de usuario. + +Ahora por fin podemos crear nuestro primer post: + + >>> Post.objects.create(author = me, title = 'Titulo simple', text = 'Test') + + +¡Hurra! ¿Quieres comprobar si ha funcionado? + + >>> Post.objects.all() + [] + + +### Agrega más posts + +Ahora puedes divertirte un poco y añadir más posts para ver cómo funciona. Añade 2 - 3 más y avanzar a la siguiente parte. + +### Filtrar Objetos + +En gran parte los QuerySets tienen la habilidad de filtrar. Digamos que queremos encontrar todos los mensajes que son escritos por el usuario ola. Utilizaremos el `filter` en lugar de `all` en `Post.objects.all()`. Entre paréntesis indicará qué condición(es) debe coincidir por una entrada de blog en nuestro queryset. En nuestra situación es `author` que es igual a `me`. La manera de escribirlo en Django es: `author = me`. Ahora nuestro código tiene este aspecto: + + >>> Post.objects.filter(author=me) + [, , , ] + + +¿O tal vez queremos ver todos los mensajes que contienen una palabra 'título' en el campo `title`? + + >>> Post.objects.filter(title__contains='title') + [, ] + + +> **Nota** Hay dos caracteres de subrayado (`_`) entre el `title` y `contains`. Django ORM utiliza esta sintaxis para separar los nombres de campo ("title") y operaciones o filtros ("contains"). Si sólo utilizas un carácter de subrayado, obtendrás un error como "FieldError: Cannot resolve keyword title_contains". + +También puedes obtener una lista de todos los mensajes publicados. Lo hacemos filtrando todos los post que tienen `published_date`: + + >>> Post.objects.filter(published_date__isnull=False) + [] + + +Lamentablemente, ninguno de nuestros mensajes son publicado todavía. Podemos cambiar eso. Primero obtener una instancia de un post que queremos publicar: + + >>> post = Post.objects.get(id=1) + + +Y luego publicarlo con nuestro método de `publish`! + + >>> post.publish() + + +Ahora intenta obtener lista de mensajes publicados otra vez (presiona 3 veces el botón de la flecha hacia arriba y pulse Enter): + + >>> Post.objects.filter(published_date__isnull=False) + [] + + +### Ordenando Objetos + +Los QuerySets también permite ordenar la lista de objetos. Tratemos de pedirlos por `created_date` : + + >>> Post.objects.order_by('created_date') + [, , , ] + + +También podemos invertir el orden agregando `–` al principio: + + >>> Post.objects.order_by('-created_date') + [, , , ] + + +¡Genial! Ahora estás listo para la siguiente parte! Para cerrar el shell, escribe esto: + + >>> exit() + $ \ No newline at end of file diff --git a/es/django_start_project/README.md b/es/django_start_project/README.md new file mode 100755 index 00000000000..a63aaf0d9bd --- /dev/null +++ b/es/django_start_project/README.md @@ -0,0 +1,108 @@ +# Tu primer proyecto en Django! + +> Parte de este capitulo esta basado en los tutoriales de Geek Girls Carrots (http://django.carrots.pl/). +> +> Parte de este capítulo se basa en el [django-marcador tutorial][1] bajo licencia de Creative Commons Attribution-ShareAlike 4.0 internacional. El tutorial de django-marcador tiene derechos de autor de Markus Zapke-Gündemann et al. + + [1]: http://django-marcador.keimlink.de/ + +Vamos a crear un simple blog! + +El primer paso para crearlo es para iniciar un nuevo proyecto en Django. Básicamente, esto significa que podrás correr algunos scripts proporcionados por Django que creará el esqueleto de un proyecto para nosotros: un montón de directorios y archivos que vamos a utilizar más adelante. + +Los nombres de algunos archivos y directorios son muy importantes para Django. No deberías renombrar los archivos que estamos a punto de crear. Moverlos a un lugar diferente tampoco es una buena idea. Django tiene que mantener una cierta estructura para ser capaz de encontrar cosas importantes. + +En la consola debe ejecutar (Recuerde de no escribir `(myvenv) ~/djangogirls$`, OK?): + +> Recuerde correr to en el entorno virtual. Si no ves un prefijo `(myvenv)` en tu consola necesitas activar tu virtualenv. Explicamos cómo hacer eso en el capítulo de **instalación de Django** en el capitulo **Trabajando con virtualenv**. + +Ejecutar en Windows: + + (myvenv) ~/djangogirls$ python myvenv\Scripts\django-admin.py startproject mysite . + + +o en Linux o Mac OS: + + (myvenv) ~/djangogirls$ django-admin startproject mysite . + + +> **Nota** Verifica que incluiste el punto (`.`) al final del comando, es importante. + +`django-admin` es un script que creará los archivos y directorios para ti. Ahora debes tener un directorio de la estructura que se parece a esto: + + djangogirls + ├───manage.py + └───mysite + settings.py + urls.py + wsgi.py + __init__.py + + +`manage.py` es un script que ayuda con la administración del sitio. Con ello podremos iniciar un servidor web en nuestro ordenador sin necesidad de instalar nada, entre otras cosas. + +El archivo `settings.py` contiene la configuración de tu sitio Web. + +¿Recuerdas cuando hablamos de un cartero que debía comprobar donde entregar una carta? `URLs.py` contiene una lista de los patrones utilizados por `urlresolver`. + +Ignoremos los otros archivos por ahora - no los cambiaremos. Lo único que debes recordar es no borrarlos por accidente! + +## Cambiando la configuración + +Vamos a hacer algunos cambios en `mysite/settings.py`. Abre el archivo usando el editor de código que has instalado anteriormente. + +Sería bueno tener la hora correcta en nuestra página web. Vaya a http://en.wikipedia.org/wiki/List_of_tz_database_time_zones y copia tu zona horaria correspondiente (TZ). (eg. `Europe/Berlin`) + +Encuentra las líneas que contienen `USE_TZ` y `TIME_ZONE` y modificalas para parecerse a esto, sustituyendo `Europe/Berlin` con tu zona horaria correspondiente: + + USE_TZ = False + TIME_ZONE = 'Europe/Berlin' + + +## Configurar una base de datos + +Hay un montón de software de base de datos diferente que puede almacenar datos para tu sitio. Utilizaremos uno por defecto, `sqlite3`. + +Este ya está configurado en esta parte del archivo `mysite/settings.py`: + + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } + } + + +Para crear una base de datos para nuestro blog, hagamos lo siguiente en la consola: `python manage.py migrate` (tenemos que estar en el directorio `djangogirls` que contiene el archivo `manage.py`). Si todo va bien, deberías ver algo como esto: + + (myvenv) ~/djangogirls$ python manage.py migrate + Operations to perform: + Apply all migrations: admin, contenttypes, auth, sessions + Running migrations: + Applying contenttypes.0001_initial... OK + Applying auth.0001_initial... OK + Applying admin.0001_initial... OK + Applying sessions.0001_initial... OK + + +Y terminamos! Tiempo para iniciar el servidor web y ver si está funcionando nuestro sitio web! + +Tienes que estar en el directorio que contiene el archivo `manage.py` (el directorio `djangogirls`). En la consola, podemos empezar el servidor web mediante la ejecución de `python manage.py runserver`: + + (myvenv) ~/djangogirls$ python manage.py runserver + + +Ahora todo lo que necesitas hacer es verificar que tu sitio web esté ejecutándose - abre tu navegador (Firefox, Chrome, Safari, Internet Explorer o lo que utilices) e introduce la dirección: + + http://127.0.0.1:8000/ + + +El servidor web se encargará de su terminal de comando hasta detenerlo: para escribir más comandos abre una nueva ventana de terminal (y no te olvides de activar tu virtualenv en él también), o detener el servidor web y presionar CTRL + C - (en Windows, tendrás que presione Ctrl+Inter). + +¡Felicidades! Has creado tu primer sitio web y ejecutado un servidor web. ¿No es genial? + +![¡Funcionó!][2] + + [2]: images/it_worked2.png + +¿Listo para el siguiente paso? Es hora de crear algo de contenido! \ No newline at end of file diff --git a/es/django_start_project/images/it_worked2.png b/es/django_start_project/images/it_worked2.png new file mode 100644 index 00000000000..4412ecfc49e Binary files /dev/null and b/es/django_start_project/images/it_worked2.png differ diff --git a/es/django_templates/README.md b/es/django_templates/README.md new file mode 100755 index 00000000000..1e185115972 --- /dev/null +++ b/es/django_templates/README.md @@ -0,0 +1,75 @@ +# Plantillas de Django + +Es hora de mostrar algunos datos! Django nos da algo de ayuda, construyendo **template tags** para ello. + +## ¿Qué son las etiquetas de plantilla? + +Verás en HTML, no puedes realmente poner código Python, porque los navegadores no lo entienden. Ellos sólo saben HTML. Sabemos que HTML es algo estático, mientras que Python es mucho más dinámico. + +**Etiquetas de plantilla Django** nos permiten transferir Python-como cosas en HTML, así que usted puede construir sitios web dinámicos más rápido y fácil. ¡ Huy! + +## Plantillas de listas de Post + +En el capítulo anteriordimos a nuestra plantilla una lista de posts en la variable `posts`. Ahora lo mostraremos en HTML. + +Para imprimir una variable en la plantilla de Django, utilizamos llaves dobles con el nombre de la variable dentro, así: + + {{ posts }} + + +Prueba esto en tu plantilla `blog/templates/blog/post_list.html` (reemplaza todo entre la segunda etiqueta `
` con `{{ posts }}`), guarda el archivo y actualiza la página para ver el resultado: + +![Figura 13.1][1] + + [1]: images/step1.png + +Como puedes ver, todo lo que obtenemos es esto: + + [< post: mi segundo post >, < Post: mi primer post >] + + +Esto significa que Django lo entiende como una lista de objetos. ¿Recuerdas de **Introducción a Python,** ¿cómo podemos mostrar listas? Sí, con el ciclo for! En una plantilla de Django, los haces de esta manera: + + {% for post in posts %} {{ post }}{% endfor %} + + +Pruebe esto en tu plantilla. + +![Figura 13.2][2] + + [2]: images/step2.png + +¡ Funciona! Pero queremos que se muestre como los posts estáticos que creamos anteriormente en el capítulo de **Introducción a HTML**. Usted puede mezclar HTML y etiquetas de plantilla. Nuestro `body` se verá así: + + < div >< h1 >< a href = "/" > Django chicas Blog < /a >< / h1 >< / div >{% for post in posts %} < div >< p > publicado: {{ post.published_date }} < /p >< h1 >< a href = "" >{{ post.title }} < /a >< / h1 >< p >{{ post.text|linebreaks }} < /p >< / div >{% endfor %} + + +Todo lo que pones entre `{% for %}` y `{% endfor %}` se repetirá para cada objeto en la lista. Actualizar la página: + +![Figura 13.3][3] + + [3]: images/step3.png + +¿Has notado que utilizamos una notación diferente esta vez `{{ post.title }}` o `{{ post.text }}`? Estamos accediendo a datos en cada uno de los campos definidos en nuestro modelo `Post`. También el `|linebreaks` es un filtro para convertir saltos de línea en los párrafos. + +## Una cosa más + +Sería bueno ver si tu sitio sigue funcionando en Heroku, ¿no? Intentemos implementarlo nuevamente. Si olvidaste como hacerlo, revisa el final del capítulo 15: + + $ git status + ... + $ git add -A . + $ git status + ... + $ git commit -m "Used Django templates instead of static HTML." + ... + $ git push heroku master + + +¡ Felicidades! Ahora seguir adelante y trata de agregar un nuevo post en tu administración de Django (recuerde añadir published_date!), luego actualizar lau página para ver si aparece el nuevo post. + +¿Funciona como un encanto?. Estamos orgullosos! Regálate algo dulce, te lo has ganado :) + +![Figura 13.4][4] + + [4]: images/donut.png \ No newline at end of file diff --git a/es/django_templates/images/donut.png b/es/django_templates/images/donut.png new file mode 100644 index 00000000000..64d38b4e889 Binary files /dev/null and b/es/django_templates/images/donut.png differ diff --git a/es/django_templates/images/step1.png b/es/django_templates/images/step1.png new file mode 100644 index 00000000000..113e145c943 Binary files /dev/null and b/es/django_templates/images/step1.png differ diff --git a/es/django_templates/images/step2.png b/es/django_templates/images/step2.png new file mode 100644 index 00000000000..464a7645731 Binary files /dev/null and b/es/django_templates/images/step2.png differ diff --git a/es/django_templates/images/step3.png b/es/django_templates/images/step3.png new file mode 100644 index 00000000000..b56b64f142e Binary files /dev/null and b/es/django_templates/images/step3.png differ diff --git a/es/django_urls/README.md b/es/django_urls/README.md new file mode 100755 index 00000000000..aa2399165f6 --- /dev/null +++ b/es/django_urls/README.md @@ -0,0 +1,100 @@ +# Django urls + +Vamos a construir nuestra primera página web - una página para tu blog! Pero primero, vamos a aprender un poco sobre Django urls. + +## ¿Qué es una URL? + +Una URL es simplemente una dirección web, puedes ver una URL cada vez que visitas cualquier sitio web - es visible en la barra de direcciones de tu navegador (¡Sí! `127.0.0.1:8000` es una URL. Y http://djangogirls.com es también una dirección URL): + +![URL][1] + + [1]: images/url.png + +Cada página en la Internet necesita su propia dirección URL. De esta manera su aplicación sabe lo que debe mostrar a un usuario que abre una dirección URL. En Django se usa algo llamado `URLconf` (configuración de URL), que es un conjunto de patrones que Django intentará hacer coincidir con la dirección URL recibida para encontrar la vista correcta. + +## ¿Cómo funcionan las URLs en Django? + +Vamos a abrir el archivo `mysite/urls.py` y ver lo que aparece: + + from django.conf.urls import patterns, include, url + from django.contrib import admin + + urlpatterns = patterns('', + # Examples: + # url(r'^$', 'mysite.views.home', name='home'), + # url(r'^blog/', include('blog.urls')), + + url(r'^admin/', include(admin.site.urls)), + ) + + +Como puedes ver, Django ya puso algo aquí para nosotros. + +Las líneas que comienzan con `#` son comentarios - significa que esas líneas no serán ejecutadas por Python. Muy útil, verdad? + +Ya está aquí la URL de admin, que visitaste en el capítulo anterior: + + url(r'^admin/', include(admin.site.urls)), + + +Esto significa que para cada URL que empieza con `admin /` Django encontrará un *view*. En este caso vamos a incluir muchas URLs a admin para que eso es mejor empacar todo en este pequeño archivo - es más legible y limpio. + +## Regex + +¿Te preguntas cómo Django coincide con las direcciones URL a las vistas? Bueno, esta parte es difícil. Django utiliza `regex`--expresiones regulares. Regex tiene muchos (un montón!) de normas que forman un patrón de búsqueda. No es tan fácil de entender así que no te preocupes hoy y sin duda los conocerás y utilizaras en el futuro. Hoy vamos a utilizar sólo los que necesitamos. + +Aquí hay un simple ejemplo para no atrapar esta frase: imagina que tienes un sitio web con la dirección: `http://www.mysite.com/post/12345/`, donde `12345` es el número de tu post. Escribir vistas separadas para todos los números de post sería muy molesto. Django facilita permitiéndole escribir `http://www.mysite.com/post/ número /`. Django se encargará del resto! + +## Tu primer url Django! + +Es hora de crear nuestro primer URL! Queremos http://127.0.0.1:8000 / para ser una presentación de nuestro blog y mostrar una lista de posts. + +También queremos limpiar el archivo `mysite/urls.py`, así que vamos a importar urls desde nuestra aplicación de `blog` en el archivo principal `mysite/urls.py`. + +Adelante, eliminar las líneas comentadas (líneas que comienzan con `#`) y añadir una línea que va a importar en el principal (url `blog.urls``''`). + +El archivo `mysite/urls.py` ahora debe verse así: + + from django.conf.urls import patterns, include, url + from django.contrib import admin + + urlpatterns = patterns('', + url(r'^admin/', include(admin.site.urls)), + url(r'', include('blog.urls')), + ) + + +Django redirigirá ahora todo lo que entre en `http://127.0.0.1:8000 /` a `blog.urls` y esperara para más instrucciones. + +## blog.urls + +Cree un nuevo archivo vacío `blog/urls.py`. ¡Muy bien! Añade estas dos primeras líneas: + + from django.conf.urls import patterns, include, url + from . import views + + +Aquí nosotros sólo importaremos métodos de Django y todas nuestras `vistas` de aplicación `blog` (aún no tenemos ninguna, pero llegaremos a eso en un minuto!) + +Después de eso, podemos agregar nuestro primer patrón de URL: + + urlpatterns = patterns('', + url(r'^$', views.post_list), + ) + + +Como puedes ver, estamos asignando una `vista` denominada `post_list` a la `^ $` URL. Pero, ¿qué hace`^ $`? Es una magia regex :) Lo desglosemos:-`^` en regex significa "el principio"; de este signo podemos empezar buscando nuestro patrón - `$` si coincide sólo "el fin" de la cadena, lo que significa que vamos a terminar buscando nuestro patrón aquí + +Si pones estos dos signos juntos, parece que estamos buscando una cadena vacía! Y eso es correcto, porque en la resolución de Django url, `http://127.0.0.1:8000 /` no es parte de la URL. Este patrón mostrará a Django que `views.post_list` es el lugar perfecto para ir si alguien entra en su sitio de Internet en la dirección `http://127.0.0.1:8000 /`. + +¿Todo bien? Abre http://127.0.0.1:8000 en tu navegador para ver el resultado. + +![Error][2] + + [2]: images/error1.png + +No "funciona", ¿eh? No te preocupes, es sólo una página de error, nada que temer. Son en realidad muy útiles: + +Se puede leer que no existe ningún atributo **'post_list'**. *¿Post_list* lo recuerdas? Esto es lo que llamamos nuestro punto de vista! Esto significa que todo esté en su lugar, simplemente no creamos nuestra *view* todavía. No te preocupes, llegaremos ahí. + +> Si quieres saber más sobre Django URLconfs, mira la documentación oficial: https://docs.djangoproject.com/en/1.7/topics/http/urls/ \ No newline at end of file diff --git a/es/django_urls/images/error1.png b/es/django_urls/images/error1.png new file mode 100644 index 00000000000..cc17593d19d Binary files /dev/null and b/es/django_urls/images/error1.png differ diff --git a/es/django_urls/images/url.png b/es/django_urls/images/url.png new file mode 100644 index 00000000000..6cd1bd96291 Binary files /dev/null and b/es/django_urls/images/url.png differ diff --git a/es/django_views/README.md b/es/django_views/README.md new file mode 100755 index 00000000000..cf1fc672069 --- /dev/null +++ b/es/django_views/README.md @@ -0,0 +1,37 @@ +# Vistas de Django - es hora de crear! + +Es hora de deshacerse de el error que hemos creado en el último capítulo :) + +Una *View* es un lugar donde ponemos la «lógica» de nuestra aplicación. Se solicitará información del `model` que se creo anteriormente y pasarlo a una `view` que va a crearse en el próximo capítulo. Las vistas son sólo métodos de Python que son un poco más complicados que lo que hicimos en el capítulo de **Introducción a Python**. + +Las Vistas se colocan en el archivo `views.py`. Agregaremos nuestras *vistas* al archivo `blog/views.py`. + +## blog/views.py + +Bien, vamos abrir este archivo y ver lo que contiene: + + from django.shortcuts import render + + # Create your views here. + + +No, demasiadas cosas aquí todavía. La simple *view* puede verse como esto: + + def post_list(request): + + return render(request, 'blog/post_list.html', {}) + + +Como puedes ver, hemos creado un método (`def`) llamado `post_list` que contiene un `request` y `return` de un método, el `render` se redirigira a nuestra plantilla `blog/post_list.html`. + +En seguida, guarde el archivo, y dirígete a tu navegador a http://127.0.0.1:8000 / para ver lo que tenemos ahora. + +Otro error! Lee lo que está pasando ahora: + +![Error][1] + + [1]: images/error.png + +Esto es fácil: *TemplateDoesNotExist*. Vamos a arreglar este error, creando una plantilla en el siguiente capítulo! + +> Aprenda más acerca de las vistas de Django mediante la lectura de la documentación oficial: https://docs.djangoproject.com/en/1.7/topics/http/views/ \ No newline at end of file diff --git a/es/django_views/images/error.png b/es/django_views/images/error.png new file mode 100644 index 00000000000..391c9e61e16 Binary files /dev/null and b/es/django_views/images/error.png differ diff --git a/es/domain/README.md b/es/domain/README.md new file mode 100755 index 00000000000..5414fea3888 --- /dev/null +++ b/es/domain/README.md @@ -0,0 +1,71 @@ +# Dominio + +Heroku le entregó un dominio pero es largo, dificil de recordar y feo. Seria asombroso contar con un nombre de dominio que sea sencillo y facil de recordar, ¿verdad? + +En este capitulo te enseñaremos como adquirir un dominio dirigirlo a Heroku! + +## ¿Donde registrar un dominio? + +Un dominio normalmente cuesta alrededor de 15 dolares estadounidenses anuales. Existen opciones un poco mas baratas y otras un poco mas caras pero esto depende del proveedor. Existen muchas compañias donde puedes adquirir un dominio: una simple [busqueda en google][1] te dara miles de opciones. Hay opciones más baratas y más caras, dependiendo del proveedor. Hay una gran cantidad de empresas que se pueden comprar un dominio de: una simple [búsqueda en google][1] dará cientos de opciones. + + [1]: https://www.google.com/search?q=register%20domain + +Nuestra opción predilecta es [I Want my name][2]. Ellos se promueven como una opción "indolora para el manejo de dominios" y realmente lo son. + + [2]: https://iwantmyname.com + +## ¿Como registrar un dominio en IWantMyName? + +Dirígete a [iwantmyname][3] y escriba un dominio que deseas tener en el cuadro de búsqueda. + + [3]: http://iwantmyname.com + +![][4] + + [4]: images/1.png + +Ahora deberías ver una lista de todos los dominios disponibles con el término que pusiste en el cuadro de búsqueda. Como puedes ver, una cara sonriente indica que el dominio está disponible para comprarlo, y una cara triste indica que no se encuentra disponible. + +![][5] + + [5]: images/2.png + +Hemos decidido comprar `djangogirls.in`: + +![][6] + + [6]: images/3.png + +Dirígete a la caja. Ahora debes registrare en iwantmyname, si todavía no tienes una cuenta. Después de eso, debes de proporcionar la información de tu tarjeta de crédito y finalmente podrás comprar el dominio! + +Después de eso, Haz clic en `Dominios` en el menú y elige el dominio que acabas de adquirir. A continuación, busca y da clic en el enlace de `manage DNS records`: + +![][7] + + [7]: images/4.png + +Ahora necesitas localizar este formulario: + +![][8] + + [8]: images/5.png + +Y llenarlo con los siguientes datos: - Nombre de hosting: www - Tipo: CNAME - Valor: tu dominio de Heroku (por ejemplo djangogirls.herokuapp.com) - TTL: 3600 + +![][9] + + [9]: images/6.png + +En la parte inferior, da clic en el botón Agregar y poder guardar los cambios. + +Puede tomar un par de horas para que tu dominio empece a trabajar, así que mantente paciente! + +## Configurar dominio en Heroku + +También tienes que decirle a Heroku que deseas utilizar su dominio personalizado. + +Dirígete a [Heroku Dashboard][10], inicia sesión con tu cuenta de Heroku y elije tu aplicación. Enseguida, configura tu aplicación y agrega tu dominio en la sección de `dominios` y guardar los cambios. + + [10]: https://dashboard.heroku.com/apps + +Eso es todo! \ No newline at end of file diff --git a/es/domain/images/1.png b/es/domain/images/1.png new file mode 100644 index 00000000000..97a06e28f2a Binary files /dev/null and b/es/domain/images/1.png differ diff --git a/es/domain/images/2.png b/es/domain/images/2.png new file mode 100644 index 00000000000..604fd5b02c8 Binary files /dev/null and b/es/domain/images/2.png differ diff --git a/es/domain/images/3.png b/es/domain/images/3.png new file mode 100644 index 00000000000..c941c0d231d Binary files /dev/null and b/es/domain/images/3.png differ diff --git a/es/domain/images/4.png b/es/domain/images/4.png new file mode 100644 index 00000000000..dcbe145b271 Binary files /dev/null and b/es/domain/images/4.png differ diff --git a/es/domain/images/5.png b/es/domain/images/5.png new file mode 100644 index 00000000000..778765053e5 Binary files /dev/null and b/es/domain/images/5.png differ diff --git a/es/domain/images/6.png b/es/domain/images/6.png new file mode 100644 index 00000000000..52a0bb87c4c Binary files /dev/null and b/es/domain/images/6.png differ diff --git a/es/dynamic_data_in_templates/README.md b/es/dynamic_data_in_templates/README.md new file mode 100755 index 00000000000..4fdb39bde50 --- /dev/null +++ b/es/dynamic_data_in_templates/README.md @@ -0,0 +1,66 @@ +# Querysets de Django + +Tenemos diferentes piezas en su lugar: el modelo `Post` está definido en `models.py`, tenemos a `post_list` en `views.py` y la plantilla agregada. ¿Pero cómo le haremos realmente para que nuestras publicaciones aparezcan en nuestra plantilla de HTML? Porque eso es lo que queremos hacer: tomar algún contenido (modelos guardados en la base de datos) y mostrarlo adecuadamente en nuestra plantilla, ¿no? + +Esto es exactamente lo que las *vistas* (views) se supone que hacen: conectar modelos con plantillas. En nuestra *vista* `post_list` necesitaremos tomar los modelos que deseamos mostrar y pasarlos a una plantilla. Así que básicamente en una *vista* decidimos qué (modelo) se mostrará en una plantilla. + +Muy bien, ahora ¿cómo lo hacemos? + +Necesitamos abrir nuestro archivo `blog/views.py`. Hasta ahora la *vista* `post_list` se ve así: + + from django.shortcuts import render + + def post_list(request): + return render(request, 'blog/post_list.html', {}) + + +¿Recuerdas cuando hablamos de incluir código en diferentes archivos? Ahora tenemos que incluir el modelo que definimos en el archivo `models.py`. Agregaremos la linea `from .models import Post` de la siguiente forma: + + from django.shortcuts import render + from .models import Post + + +El punto después de `from` indica el *directorio actual* o la *aplicación actual*. Como `views.py` y `models.py` están en el mismo directorio, simplemente usamos `.` y el nombre del archivo (sin `.py`). Ahora importamos el nombre del modelo (`Post`). + +¿Pero ahora qué sigue? Para tomar publicaciones reales del modelo `Post`, necesitamos algo llamado `QuerySet` (conjunto de consultas). + +## QuerySet + +Ya debes estar familiarizado con la forma en que funcionan los QuerySets. Hablamos de ellos en el [capítulo Django ORM (QuerySets)][1]. + + [1]: /django_orm/README.html + +Entonces ahora nos interesa una lista de entradas del blog que han sido publicadas y ordenadas por `published_date` (fecha de publicación), no? Ya hicimos eso en el capítulo QuerySets! + + Post.objects.filter(published_date__isnull=False).order_by('published_date') + + +Ahora agregamos esta parte del código en el archivo `blog/views.py`, agregándolo a la función `def post_list(request)`: + + from django.shortcuts import render + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__isnull=False).order_by('published_date') + return render(request, 'blog/post_list.html', {}) + + +Observa que creamos una *variable* en nuestro QuerySet: `posts`. Tómalo como el nombre de nuestro QuerySet. De aquí en adelante vamos a referirnos al QuerySet con ese nombre. + +La última parte es pasar el QuerySet `posts` a la plantilla (veremos cómo mostrarla en el siguiente capítulo). + +En la función `render` ya tenemos el parámetro `request` (todo lo que recibimos del usuario via Internet) y el archivo `'blog/post_list.html'` como plantilla. El último parámetro, que se ve así: `{}` es un campo en el que podemos agregar algunas cosas para que la plantilla las use. Necesitamos nombrarlos (le seguiremos llamando `'posts'` por mientras :)). Se debe ver así: `{'posts': posts}`. Observa que la parte que va antes de `:` está en comillas `''`. + +Finalmente nuestro archivo `blog/views.py` debe verse así: + + from django.shortcuts import render + from .models import Post + + def post_list(request): + posts = Post.objects.filter(published_date__isnull=False).order_by('published_date') + return render(request, 'blog/post_list.html', {'posts': posts}) + + +¡Terminamos! Ahora regresemos a nuestra plantilla y mostremos este QuerySet. + +Si quieres leer un poco más acerca de QuerySets en Django, puedes darle un vistazo a: https://docs.djangoproject.com/en/1.7/ref/models/querysets/ \ No newline at end of file diff --git a/es/extend_your_application/README.md b/es/extend_your_application/README.md new file mode 100755 index 00000000000..18c6a6d1e5e --- /dev/null +++ b/es/extend_your_application/README.md @@ -0,0 +1,181 @@ +# Extiende tu aplicación + +Ya hemos completado todos los pasos necesarios para la creación de nuestro sitio web: sabemos cómo escribir un model, url, view y template. También sabemos cómo hacer que nuestro sitio web. + +Tiempo para practicar! + +Lo primero que necesitamos en nuestro blog, es obviamente, una página para mostrar un post, ¿cierto? + +Ya tenemos un modelo `Post`, así que no necesitamos añadir nada a `models.py`. + +## Crea un enlace en la plantilla + +Vamos a empezar añadiendo un enlace dentro del archivo `blog/templates/blog/post_list.html`. Hasta el momento debe verse así: + + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} + {% endblock content %} + + +Queremos tener un enlace a una página de detalle sobre el título del post. Vamos a cambiar `< h1 >< a href = "" >{{ post.title }} < /a >< / h1 >` dentro del enlace: + +

{{ post.title }}

+ + +Tiempo para explicar lo misterioso `{% url 'blog.views.post_detail' pk=post.pk %}`. Como sospechas, la notación `{% %}` significa que estamos utilizando Django template tags. Esta vez vamos a utilizar uno que va a crear una dirección URL para nosotros! + +`blog.views.post_detail` es una ruta hacia `post_detail` *view* que queremos crear. Por favor nota: `blog` es el nombre de nuestra aplicación (el `blog` de directorio), `views` es el nombre del archivo `views.py` y `post_detail` - es el nombre de la *view*. + +Ahora cuando vayamos a: + + http://127.0.0.1:8000/ + + +Tendremos un error (como era de esperar, ya que no tenemos una dirección URL o una *viwe* para `post_detail`). Se verá así: + +![NoReverseMatch error][1] + + [1]: images/no_reverse_match2.png + +Vamos a crear una dirección URL en `urls.py` para nuestro `post_detail` *view*! + +### URL: http://127.0.0.1:8000/post/1/ + +Queremos crear una dirección URL de Django a una *view* denominada `post_detail`, que mostrará una entrada del blog. ¿Agrega la línea `url (r'^ poste / (?P < pk >[0-9] +) / $', views.post_detail),` en el archivo `blog/urls.py`. Debe tener este aspecto: + + from django.conf.urls import patterns, include, url + from . import views + + urlpatterns = patterns('', + url(r'^$', views.post_list), + url(r'^post/(?P[0-9]+)/$', views.post_detail), + ) + + +Da miedo, pero no te preocupes - lo explicaremos para ti: - comienza con `^` otra vez, "el principio" - `post /` sólo significa que después del comienzo, la dirección URL debe contener la palabra **post** y **/**. Hasta ahora, bien. - `(?P < pk >[0-9] +)`-esta parte es más complicada. Significa que Django llevará todo lo que coloques aquí y lo transferirá a una vista como una variable llamada `pk`. `[0-9]` también nos dice que sólo puede ser un número, no es una carta (entre 0 y 9). `+` significa que tiene que haber uno o más dígitos. Por algo como `http://127.0.0.1:8000/post / /` no es válido, pero `1234567890/post/http://127.0.0.1:8000/` es perfectamente aceptable! -`/` - entonces necesitamos **/** de nuevo - `$` - "the end"! + +Eso significa que si entras en `http://127.0.0.1:8000/post/5/` en tu navegador, Django entenderá que estás buscando una *view* denominada `post_detail` y transferirá la información de `pk` que es igual a `5` a la *view*. + +`PK` es atajo para la `llave principal`. Este nombre se utiliza a menudo en proyectos de Django. Pero puedes nombrar tus variable como te gusta (Recuerda: minúscula y `_` en lugar de espacios en blanco!). Por ejemplo en lugar de `(?.¿P < pk >[0-9] +)` podríamos tener variable `post_id`, así que esto lo verías como: `(?P < post_id > [0-9] +)`. + +¡Bien! Vamos a actualizar la página: + + http://127.0.0.1:8000/ + + +¡Boom! Sin embargo otro error! Como era de esperarse! + +![AttributeError][2] + + [2]: images/attribute_error2.png + +¿Te acuerdas del próximo paso? Por supuesto: agregar una view! + +## post_detail view + +Esta vez nuestra *view* tendrá un parámetro adicional `pk`. ¿Nuestra *view* necesita atraparla, cierto? Entonces definiremos nuestra función como `def post_detail (petición, pk):`. Ten en cuenta que tenemos que usar exactamente el mismo nombre que especificamos en las urls (`pk`). Omitir esta variable es incorrecto y resultará en un error! + +Ahora, queremos sólo una entrada del blog. Para ello podemos usar querysets como esta: + + Post.objects.get(pk=pk) + + +Pero este código tiene un problema. Si no hay ningún `Post` con `llave primaria` (`pk`) tendremos un error muy feo! + +![DoesNotExist error][3] + + [3]: images/does_not_exist2.png + +No queremos eso! Pero, por supuesto, Django viene con algo que se encargará de ese problema por nosotros: `get_object_or_404`. En caso de que no haya ningún `Post` con el dado `pk` se mostrará una más agradable página ( llamada `Page Not Found 404`). + +![Page not found][4] + + [4]: images/404_2.png + +La buena noticia es que puedes crear tu propia página `Page Not Found` y diseñarla como desees. Pero por ahora, no es súper importante. + +Es hora de agregar una *view* a nuestro archivo `views.py`! + +Deberíamos abrir `blog/views.py` y agregue el siguiente código: + + from django.shortcuts import render, get_object_or_404 + + +Cerca de la líneas `from`. Y en el final del archivo añadimos nuestra *view*: + + def post_detail(request, pk): + post = get_object_or_404(Post, pk=pk) + return render(request, 'blog/post_detail.html', {'post': post}) + + +Sí. Es hora de actualizar la página: + + http://127.0.0.1:8000/ + + +![Post list view][5] + + [5]: images/post_list2.png + +¡ Funcionó! Pero ¿qué pasa cuando haces clic en un enlace en el título del post? + +![TemplateDoesNotExist error][6] + + [6]: images/template_does_not_exist2.png + +¡ Oh no! Otro error! Pero ya sabemos cómo lidiar con eso, ¿no? Tenemos que añadir una plantilla! + +Crearemos un archivo en `blog/templates/blog` llamado `post_detail.html`. + +Se verá así: + + {% extends 'blog/base.html' %} + + {% block content %} +
+ {% if post.published_date %} + {{ post.published_date }} + {% endif %} +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+ {% endblock %} + + +Una vez más estamos extendiendo `base.html`. En el bloque de `content` queremos mostrar un post published_date (si existe), título y texto. Pero deberíamos discutir algunas cosas importantes, ¿cierto? + +`{% if ... %} ... {% endif %}` es una template tag que podemos usar cuando queramos ver algo (recuerdas `if... else...` desde el capítulo de **Introducción a Python**?). En este escenario queremos comprobar si `published_date de un post` no está vacío. + +Bien, podemos actualizar nuestra página y ver si `Page Not Found` se ha ido. + +![Post detail page][7] + + [7]: images/post_detail2.png + +¡ Yay! ¡ Funciona! + +## Una cosa más: ¡Tiempo de implementación! + +Sería bueno ver si tu sitio sigue funcionando en Heroku, ¿no? Intentemos implementarlo nuevamente. Si olvidaste como hacerlo, revisa el final del capítulo 15: + + $ git status + ... + $ git add -A . + $ git status + ... + $ git commit -m "Added more views to the website." + ... + $ git push heroku master + + +¡Y eso debería ser todo! Felicidades :) \ No newline at end of file diff --git a/es/extend_your_application/images/404_2.png b/es/extend_your_application/images/404_2.png new file mode 100644 index 00000000000..a8cb53172af Binary files /dev/null and b/es/extend_your_application/images/404_2.png differ diff --git a/es/extend_your_application/images/attribute_error2.png b/es/extend_your_application/images/attribute_error2.png new file mode 100644 index 00000000000..6edcd9933c3 Binary files /dev/null and b/es/extend_your_application/images/attribute_error2.png differ diff --git a/es/extend_your_application/images/does_not_exist2.png b/es/extend_your_application/images/does_not_exist2.png new file mode 100644 index 00000000000..023d8720081 Binary files /dev/null and b/es/extend_your_application/images/does_not_exist2.png differ diff --git a/es/extend_your_application/images/no_reverse_match2.png b/es/extend_your_application/images/no_reverse_match2.png new file mode 100644 index 00000000000..db65a5dc70a Binary files /dev/null and b/es/extend_your_application/images/no_reverse_match2.png differ diff --git a/es/extend_your_application/images/post_detail2.png b/es/extend_your_application/images/post_detail2.png new file mode 100644 index 00000000000..240dc447b51 Binary files /dev/null and b/es/extend_your_application/images/post_detail2.png differ diff --git a/es/extend_your_application/images/post_list2.png b/es/extend_your_application/images/post_list2.png new file mode 100644 index 00000000000..8ae30c71311 Binary files /dev/null and b/es/extend_your_application/images/post_list2.png differ diff --git a/es/extend_your_application/images/template_does_not_exist2.png b/es/extend_your_application/images/template_does_not_exist2.png new file mode 100644 index 00000000000..335ce2569ef Binary files /dev/null and b/es/extend_your_application/images/template_does_not_exist2.png differ diff --git a/es/how_internet_works/README.md b/es/how_internet_works/README.md new file mode 100755 index 00000000000..65f2ee1590a --- /dev/null +++ b/es/how_internet_works/README.md @@ -0,0 +1,53 @@ +# Cómo funciona internet + +> Este capitulo está inspirado por la charla "How the Internet works" de Jessica McKellar (http://web.mit.edu/jesstess/www/). + +Apostamos que utilizas Internet cada día. Pero, ¿sabes lo que pasa cuando escribe una dirección como http://djangogirls.org en tu navegador y presionas 'Enter'? + +Lo primero que tienes que entender es que un sitio web es sólo un montón de archivos guardados en un disco duro. Al igual que tus películas, música o fotos. Sin embargo, los sitios web poseen una peculiaridad: ellos incluyen un código de computadoras llamado HTML. + +Si no estás familiarizado con la programación, puede ser difícil de captar HTML al principio, pero tus navegadores web (como Chrome, Safari, Firefox, etc.) lo aman. Los navegadores web están diseñados para entender este código, seguir sus instrucciones y mostrar todos esos archivos de los cuales está hecho de la manera exacta como tu quieres que se muestren. + +Como cualquier otro archivo, tenemos que guardar los archivos HTML en algún lugar de un disco duro. Para Internet, usamos unos especiales y poderosos computadores llamados* servidores*. Ellos no tienen una pantalla, ratón o teclado, debido a que su propósito es almacenar datos y servirlos. Por esa razón son llamados *servidores* -- porque ellos *sirven* los datos. + +OK, quizás te preguntes ¿como luce Internet, cierto? + +Te hemos hecho una imagen! luce algo como esto: + +![Figura 1.1][1] + + [1]: images/internet_1.png + +Parece un lío, ¿no? En realidad es una red de máquinas conectadas (los mencionados *servidores*). ¡Cientos de miles de máquinas! Muchas, muchos kilómetros de cables alrededor del mundo! Puedes visitar el siguiente sitio web donde muestra las conexiones de cables submarinos al rededor del mundo(http://submarinecablemap.com/) para ver lo complicado que es la red. Aquí hay una captura de pantalla de la página web: + +![Figura 1.2][2] + + [2]: images/internet_3.png + +Es fascinante, ¿no? Pero obviamente, no es posible tener un cable entre cada máquina conectada a Internet. Así que, para llegar a una máquina (por ejemplo la aloja a http://djangogirls.org) tenemos que pasar una solicitud a través de muchas máquinas diferentes. + +Se parece a esto: + +![Figura 1.3][3] + + [3]: images/internet_2.png + +imagina que cuando escribes http://djangogirls.org, estas escribiendo una carta que dice: "Queridos jango Girls, me gustaría ver su sitio web djangogrils.org. Por favor, envíenmelo!" + +Tu carta va hacia la oficina de correo más cercana. Luego va a otra un poco más cercana de su destinatario, luego a otra y a otra hasta que es entregada en su destino. Lo único es que si usted envía cartas (*paquetes de datos*) con frecuencia al mismo lugar, cada carta puede pasar por oficinas de correos (*routers*) totalmente diferentes, dependiendo de cómo se distribuyen en cada oficina. + +![Figura 1.4][4] + + [4]: images/internet_4.png + +Sí, es tan simple como eso. Enviar mensajes y esperar alguna respuesta. Por supuesto, en vez de papel y pluma usas bytes de datos, pero la idea es la misma! + +En lugar de direcciones con el nombre de la calle, ciudad, código postal y nombre del país, utilizamos direcciones IP. tu computador pide primero el DNS (Domain Name System, en español "Sistema de Nombres de Dominio") para traducir djangogirls.org a una dirección IP. funciona un tanto parecido a los directorio telefónicos donde se busca el nombre de la persona que se desea contactar y este nos muestra su número de teléfono y dirección. + +Cuando envías una carta, ésta necesita tener ciertas características para ser entregada correctamente: una dirección, sello etc. También utilizas un lenguaje que el receptor pueda entender, ¿cierto? Lo mismo sucede con *los paquetes de daots* que envías para ver un sitio web: utilizas un protocolo llamado HTTP (Hypertext Transfer Protocol, en español protocolo de transferencia de hipertexto). + +Así que, básicamente, cuando tienes un sitio web necesitas tener un *servidor* (la máquina) donde vive. El *servidor* está esperando cualquier *solicitud entrante* (cartas que piden al servidor para que envié tu sitio web) y éste responde enviado tu sitio web (en otra carta). + +Puesto que este es un tutorial de Django, seguro te preguntarás qué es lo que hace Django. Bueno, cuando envías una respuesta, no siempre quieres enviar lo mismo a todo el mundo. Es mucho mejor si tus cartas son personalizados, especialmente para la persona que acaba de escribir, ¿cierto? Django nos ayuda con la creación de estas cartas personalizadas, interesante :). + +así que basta de charlas y pongamos manos a la obra! \ No newline at end of file diff --git a/es/how_internet_works/images/internet_1.png b/es/how_internet_works/images/internet_1.png new file mode 100644 index 00000000000..9c5bcf0b003 Binary files /dev/null and b/es/how_internet_works/images/internet_1.png differ diff --git a/es/how_internet_works/images/internet_2.png b/es/how_internet_works/images/internet_2.png new file mode 100644 index 00000000000..dd5861f376f Binary files /dev/null and b/es/how_internet_works/images/internet_2.png differ diff --git a/es/how_internet_works/images/internet_3.png b/es/how_internet_works/images/internet_3.png new file mode 100644 index 00000000000..a23488e3f2f Binary files /dev/null and b/es/how_internet_works/images/internet_3.png differ diff --git a/es/how_internet_works/images/internet_4.png b/es/how_internet_works/images/internet_4.png new file mode 100644 index 00000000000..05f1aed562f Binary files /dev/null and b/es/how_internet_works/images/internet_4.png differ diff --git a/es/html/README.md b/es/html/README.md new file mode 100755 index 00000000000..ecf2ae4fa3e --- /dev/null +++ b/es/html/README.md @@ -0,0 +1,184 @@ +# Introducción a HTML + +Qué es una plantilla, te estarás preguntando? + +Una plantilla es un archivo que podemos utilizar nuevamente para presentar información en un formato homogéneo - por ejemplo, se podría utilizar una plantilla para ayudarte a escribir una carta, porque aunque cada carta puede contener un mensaje distinto y dirigirse a una persona diferente, compartirán el mismo formato. + +El formato de una plantilla de Django se describe en un lenguaje llamado HTML (que es el código HTML que mencionamos en el primer capítulo **Como funciona Internet**). + +## ¿Qué es HTML? + +HTML es un simple código que es interpretado por el navegador web - como Chrome, Firefox o Safari - para mostrar una página web al usuario. + +HTML por separado es "Lenguaje Marcado de HiperTexto". **HiperTexto** significa que es un tipo de texto que soporta hipervínculos entre páginas. **Marcado** significa que hemos tomado un documento y lo marca con código para decirte cómo interpretar la página (en este caso, un navegador). El código HTML está construido con las **etiquetas**, cada uno a partir de `<` y terminando con `>`. Estas etiquetas de marcado son **elementos**. + +## Tu primera plantilla! + +Crear una plantilla significa crear un archivo de plantilla. Todo es un archivo, ¿verdad? Probablemente hayas notado esto ya. + +Las plantillas se guardan en el directorio de `blog/templates/blog`. Así que primero crear un directorio llamado `templates` dentro de tu directorio de blog. Luego cree otro directorio llamado `blog` dentro de su directorio de templates: + + blog + └───templates + └───blog + + +(Tal vez te preguntes por qué necesitamos dos directorios llamados `blog` - como usted descubrirá más adelante, esto es simplemente una útil convención de nomenclatura que hace la vida más fácil cuando las cosas empiezan a complicarse más.) + +Y ahora a crear un archivo `post_list.html` (Déjalo en blanco por ahora) dentro del directorio de `blog/templates/blog`. + +Cómo se ve su sitio web ahora: http://127.0.0.1:8000 / + +> Si todavía tienes un error `TemplateDoesNotExists`, intenta reiniciar el servidor. Ve a la línea de comandos, detén el servidor pulsando Ctrl + C (teclas Control y C juntas) y comienza de nuevo mediante la ejecución del comando `python manage.py runserver`. + +![Figura 11.1][1] + + [1]: images/step1.png + +Ningún error ya! Felicidades :) Sin embargo, tu sitio de Internet en realidad no publica nada, excepto una página en blanco, porque la plantilla también está vacía. Tenemos que arreglarlo. + +Añade lo siguiente a su archivo de plantilla: + + +

Hi there!

+

It works!

+ + + +¿Cómo luce ahora tu sitio de Internet? Haga clic para ver: http://127.0.0.1:8000 / + +![Figura 11.2][2] + + [2]: images/step3.png + +¡Funcionó! Buen trabajo :) + +* La etiqueta más básica, ``, es siempre el principio de cualquier página web y `` es siempre el final. Como puedes ver, todo el contenido de la página web va al principio de la etiqueta `` y entre la etiqueta de cierre `` +* `< p >` es una etiqueta para los elementos de párrafo; `< /p >` cierra cada párrafo + +## Cabeza & Cuerpo + +Cada página HTML también se divide en dos elementos: **head** y **body**. + +* **head** es un elemento que contiene información sobre el documento que no aparece en la pantalla. + +* **body** es un elemento que contiene todo lo que se muestra como parte de la página web. + +Usamos `` para decirle el navegador acerca de la configuración de la página y `` para decir lo que realmente está en la página. + +Por ejemplo, puedes ponerle un título a la página web dentro de la ``, así: + + + + Ola's blog + + +

Hi there!

+

It works!

+ + + + +Guarda el archivo y actualiza tu página. + +![Figura 11.3][3] + + [3]: images/step4.png + +¿Observa cómo el navegador ha comprendido que "Ola's Blog" es el título de su página? Ha interpretado `Ola's blog` y coloca el texto en la barra de título del navegador (también se utilizará para marcadores y así sucesivamente). + +Probablemente también hayas notado que cada etiqueta de apertura es comparable con una *etiqueta de cierre*, con un `/`, y que elementos *anidados* (es decir, no puede cerrar una etiqueta particular hasta que todos los que estaban en su interior se hayan cerrado también). + +Es como poner las cosas en cajas. Tienes una caja grande, ``; en su interior hay ``, y que contiene las cajas aún más pequeñas: `

`. + +Tienes que seguir estas reglas de etiquetas *de cierre* y de *anidar* elementos - si no lo haces, el navegador puede no ser capaz de interpretarlos correctamente y tu página se mostrará incorrectamente. + +## Personaliza tu plantilla + +Ahora puedes divertirte un poco y tratar de personalizar tu plantilla! Aquí están algunas etiquetas útiles para eso: + +* `

Un Titulo

` - para tu titulo más importante +* `

Un sub-titulo

` para el siguiente nivel +* `

Un sub-sub-titulo

` ... y así hasta `
` +* `texto` Pone en cursiva tu texto +* `texto` Pone en negrita tu texto +* `
` Un salto de línea (No puedes colocar nada dentro de br) +* `link` crea un link +* `
  • primer elemento
  • segundo elemento
` crea una lista, igual que esta! +* `
` defina una sección de la página + +Aquí hay un ejemplo de una plantilla completa: + + + + Django Girls blog + + + + +
+

published: 14.06.2014, 12:14

+

My first post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.

+
+ +
+

published: 14.06.2014, 12:14

+

My second post

+

Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Donec id elit non mi porta gravida at eget metus. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut f.

+
+ + + + +Hemos creado tres secciones `div` aquí. + +* El primer elemento `div` contiene el título de nuestro post - es un encabezado y un enlace +* Otros dos elementos `div` contengan nuestro blog con fecha publicada, `h2` con un título puesto que es clicable y dos s `p` (párrafo) de texto, uno para la fecha y uno de nuestro blogpost. + +Nos da este efecto: + +![Figura 11.4][4] + + [4]: images/step6.png + +Yaaay! Pero hasta el momento, nuestra plantilla sólo muestra exactamente **la misma información** - considerando que antes hablábamos de plantillas como permitiéndonos Mostrar información **diferente** en el **mismo formato**. + +Lo que queremos realmente es mostrar mensajes reales añadidos en nuestra administración de Django - y eso es a donde vamos. + +## Una cosa más + +¿Sería bueno ver si tu sitio de Internet esta trabajando todavía en Heroku, cierto? Vamos a intentar implementar otra vez. + +En primer lugar, veamos qué archivos han cambiado desde que hicimos deploy: + + $ git status + + +Vamos a decirle a `git` para incluir todos los cambios desde el directorio actual: + + $ git add -A . + + +> **Nota** `-A` (abreviatura de "all") significa que `git` también reconocerá si se han eliminado los archivos (de forma predeterminada, sólo reconoce archivos nuevos/modificados). También recuerda (capítulo 3) que `.` significa el directorio actual. + +Antes de que subamos todos los archivos, vamos a ver qué `git` va subiendo (todos los archivos que `git` cargará ahora deberían aparecer en verde): + + $ git status + + +Ya casi estamos, ahora es tiempo de decirle que guarde estos cambios en su historial. Vamos a dar un "mensaje de comentar" donde se describe lo que hemos cambiado. Puedes escribir cualquier cosa que te gustaría en esta etapa, pero es útil escribir algo descriptivo para que puedes recordar lo que has hecho en el futuro. + + $ git commit -m "Cambiando el html para la página." + + +> **Nota** Asegúrate de usar comillas dobles alrededor del mensaje de confirmación. + +Una vez que hemos hecho eso, por fin podemos subir (push) nuestros cambios en el sitio web en heroku: + + git push heroku master + + +Y eso es todo! Una vez terminado Heroku, tu puedes seguir adelante y actualizar tu sitio web en el navegador. Los cambios deberian ser visibles! \ No newline at end of file diff --git a/es/html/images/step1.png b/es/html/images/step1.png new file mode 100644 index 00000000000..e9c2f1082d6 Binary files /dev/null and b/es/html/images/step1.png differ diff --git a/es/html/images/step3.png b/es/html/images/step3.png new file mode 100644 index 00000000000..811226fa3fc Binary files /dev/null and b/es/html/images/step3.png differ diff --git a/es/html/images/step4.png b/es/html/images/step4.png new file mode 100644 index 00000000000..bd6c1a044e0 Binary files /dev/null and b/es/html/images/step4.png differ diff --git a/es/html/images/step6.png b/es/html/images/step6.png new file mode 100644 index 00000000000..e42a2fe5388 Binary files /dev/null and b/es/html/images/step6.png differ diff --git a/es/images/application.png b/es/images/application.png new file mode 100644 index 00000000000..6dcba6202c7 Binary files /dev/null and b/es/images/application.png differ diff --git a/es/intro_to_command_line/README.md b/es/intro_to_command_line/README.md new file mode 100755 index 00000000000..e34046e5f75 --- /dev/null +++ b/es/intro_to_command_line/README.md @@ -0,0 +1,275 @@ +# Introducción a la interfaz de línea de comandos + +Es emocionante, ¿verdad? Vas a escribir tu primera línea de código en pocos minutos :) + +**Permítenos presentarte a tu primer nuevo amigo: la línea de comandos!** + +En los siguientes pasos te mostraran como usar aquella ventana negra que todos los hackers usan. Puede parecer un aterrador al principio pero es solo un mensaje en pantalla que espera a que le des órdenes. + +## ¿Qué es la línea de comandos? + +La ventana, que generalmente es llamada **línea de comandos** o **interfaz de línea de comandos**, es una aplicación basada en texto para la ver, manejar y manipular archivos en tu computadora (como por ejemplo el Explorador de Windows o Finder en Mac, pero sin la interfaz gráfica). Otros nombres para la línea de comandos son: *cmd*, *CLI*, *el símbolo del sistema*, *consola* o *terminal*. + +## Abrir la interfaz de línea de comandos + +para empezar a experimentar con nuestra interfaz de linea de comandos lo primero que debemos hacer es abrirla. + +### Windows + +Ir al menú Inicio → todos los programas → accesorios → Command Prompt. + +### Mac OS X + +Aplicaciones → Servicios → Terminal. + +### Linux + +Esta probablemente en Aplicaciones → Accesorios → Terminal, pero eso depende de su distribución. Si no existe, Googlelo :) + +## Prompt + +Ahora deberías ver una ventana blanca o negra que está esperando tus órdenes. + +Si estás en Mac o Linux, probablemente veráz `$`, como este: + + $ + + +En Windows, es un signo así `>`, como este: + + > + + +Cada comando sera antepuesto por este signo y un espacio, pero no tienes que escribirlo. Tu computadora lo hará por ti :) + +> Sólo una pequeña nota: en su caso, tal vez hay algo como `C:\Users\ola>` o `Olas-MacBook-Air:~ ola$` antes del prompt y eso es 100% correcto. En este tutorial sólo lo hemos simplificado a lo mínimo. + +## Tu primer comando (¡ YAY!) + +Vamos a empezar con algo simple. Escribe este comando: + + $ whoami + + +o + + > whoami + + +Y luego oprime la tecla Enter. Este es el resultado: + + $ whoami olasitarska + + +Como puedes ver, la computadora sólo te presento su nombre de usuario. Bien, eh? :) + +> Trato de escribir cada comando, no copiar pegar. Te acordarás de más de esta manera! + +## Básicos + +Cada sistema operativo tiene un conjunto diferente de comandos para la línea de comandos, así que asegúrate de seguir las instrucciones para tu sistema operativo. Vamos a intentarlo, ¿de acuerdo? + +### Directorio actual + +Sería bueno saber dónde estamos ahora, ¿cierto? Vamos a ver. Escribe este comando y oprime Enter: + + $ pwd + /usuarios/olasitarska + + +Si estás en Windows: + + > cd + C:\Users\olasitarska + + +Probablemente verás algo similar en tu máquina. Una vez que abres la línea de comandos generalmente empiezan en el directorio home del usuario. + +> Nota: 'pwd' significa 'mostrar directorio de trabajo'. + +* * * + +### Lista de archivos y directorios + +¿Qué es? Sería bueno saber. Veamos: + + $ ls + Applications + Desktop + Downloads + Music + ... + + +Windows: + + > dir + Directory of C:\Users\olasitarska + 05/08/2014 07:28 PM Applications + 05/08/2014 07:28 PM Desktop + 05/08/2014 07:28 PM Downloads + 05/08/2014 07:28 PM Music + ... + + +* * * + +### Cambie el directorio actual + +¿Quizás podemos ir a nuestro directorio de escritorio? + + $ cd Desktop + + +Windows: + + > cd Desktop + + +Comprobar si realmente ha cambiado: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +¡ Aquí está! + +> PRO tip: si escribes `cd D` y luego oprimes `tab` en el teclado, la línea de comandos automáticamente Autorrellenara el resto del nombre para que puedas navegar más rápido. Si hay más de una carpeta a partir de "D", presiona el botón `tab` dos veces para obtener una lista de opciones. + +* * * + +### Crear directorio + +¿Cómo crear un directorio de Django Girls en tu escritorio? Puedes hacerlo de esta manera: + + $ mkdir djangogirls + + +Windows: + + > mkdir djangogirls + + +Este pequeño comando creará una carpeta con el nombre `djangogirls` en tu escritorio. Puede comprobar si está allí buscando en tu escritorio o ejecutando un `ls/dir`! Inténtalo :) + +> PRO tip: Si no quieres escribir una y otra vez los mismos comandos, prueba oprimiendo la `flecha arriba` y `flecha abajo` de tu teclado para recorrer a recientes comandos utilizados. + +* * * + +### Ejercicios! + +Un pequeño reto para ti: en el directorio recién creado `djangogirls` crear un directorio llamado `test`. Utilice los comandos `cd` y `mkdir`. + +#### Solución: + + $ cd djangogirls + $ mkdir test + $ ls + + +Windows: + + > cd djangogirls + > mkdir test + > dir + 08/05/2014 19:28 < DIR > test + + +¡ Felicidades! :) + +* * * + +### Limpiar + +No queremos dejar un desorden, así que vamos a eliminar todo lo que hicimos hasta ese momento. + +En primer lugar, tenemos que volver al escritorio: + + $ cd .. + + +Windows: + + > cd .. + + +Haciendo `cd` `..` cambiará el directorio actual al directorio padre (que significa el directorio que contiene el directorio actual). + +Revisa dónde estás: + + $ pwd + /Users/olasitarska/Desktop + + +Windows: + + > cd + C:\Users\olasitarska\Desktop + + +Ahora es hora de eliminar el directorio `djangogirls`. + +> **Atención**: eliminar archivos utilizando `del`, `rmdir` o `rm` es irrecuperable, lo que significa *archivos borrados desaparecerá para siempre*! Entonces, ser muy cuidadosa con este comando. + + $ rm - r djangogirls + + +Windows: + + > rmdir/s djangogirls + djangogirls, ¿estás seguro < Y/N >? Y + + +Hecho! Asegurémonos que en verdad fueron borrados, vamos a ver: + + $ ls + + +Windows: + + > dir + + +### Salida + +Eso es todo por ahora! Ahora con seguridad puedes cerrar la línea de comandos. Vamos a hacerlo al estilo hacker, bien? :) + + $ exit + + +Windows: + + > exit + + +Bueno, no? :) + +## Índice + +Aquí está una lista de algunos comandos útiles: + +| Comando (Windows) | Comando (Mac OS / Linux) | Descripción | Ejemplo | +| ----------------- | ------------------------ | ----------------------------- | ------------------------------------------------- | +| exit | exit | cierra la ventana | **exit** | +| cd | cd | Cambia el directorio | **cd test** | +| dir | ls | lista de directorios/archivos | **dir** | +| copy | cp | copia el archivo | **copy c:\test\test.txt c:\windows\test.txt** | +| move | mv | mueve el archivo | **move c:\test\test.txt c:\windows\test.txt** | +| mkdir | mkdir | Crea un nuevo directorio | **mkdir testdirectory** | +| del | rm | elimina un archivo/directorio | **del c:\test\test.txt** | + +Estos son sólo muy pocos de los comandos en la línea de comandos que puedes utilizar pero no vas a usar algo más hoy. + +Si tienes curiosidad, [ss64.com][1] contiene una referencia completa de comandos para todos los sistemas operativos. + + [1]: http://ss64.com + +## Listo? + +Vamos a sumergirnos en Python! \ No newline at end of file diff --git a/es/python_installation/README.md b/es/python_installation/README.md new file mode 100755 index 00000000000..6a7c23a49c2 --- /dev/null +++ b/es/python_installation/README.md @@ -0,0 +1,59 @@ +# Vamos a empezar con Python + +Por fin estamos aquí! + +Pero primero, déjenos decirte qué es Python. Python es un lenguaje de programación muy popular que puede utilizarse para la creación de sitios web, juegos, software de cálculo, gráficos y mucho más. + +Python se originó en la década de 1980 y su objetivo principal es ser legible por los seres humanos (no sólo las máquinas!), por eso parece mucho más simple que otros lenguajes de programación. Esto lo hace fácil de aprender, pero no te preocupes, Python es también muy poderoso! + +# Instalación de Python + +> Este subcapítulo se basa en un tutorial de Geek Girls Carrots (http://django.carrots.pl/) + +Django está escrito en Python. Necesitamos Python para cualquier cosa en Django. Vamos a empezar con la instalación! Queremos que instales Python 3.4, así que si tienes alguna versión anterior, deberás actualizarla. + +### Windows + +Puedes descargar Python para Windows desde el sitio web https://www.python.org/downloads/release/python-342/. Después de descargar el archivo ***.msi**, debes ejecutarlo (has doble clic en el archivo) y sige las instrucciones. Es importante recordar el camino (el directorio) donde se ha instalado Python. Será necesario más adelante! + +### Linux + +Es muy probable que ya tengas Python instalado. Para verificar si lo tienes (y que versión es), abrir la consola y escribe el siguiente comando: + + $ python3 --version + Python 3.4.2 + + +Si no tienes instalado Python o si deseas una versión diferente, se puede instalar de la siguiente manera: + +#### Ubuntu + +Escribe este comando en la consola: + + sudo apt-get install python3.4 + + +#### Fedora + +Usa este comando en la consola: + + sudo yum install python3.4 + + +### OS X + +Tienes que ir a la página web https://www.python.org/downloads/release/python-342/ y descargar al instalador de Python: + +* descarga el archivo *DMG* titulado *Mac OS X 64-bit/32-bit installer*, +* has doble click para abrirlo, +* Doble click en *Python.mpkg* para ejecutar al instalador. + +Verifica que la instalación se realizó correctamente abriendo la aplicación *Terminal* y ejecutando el comando `python3`: + + $ python3 --version + Python 3.4.2 + + +* * * + +Si tienes alguna duda o si algo salió mal y no tienes ni idea de qué hacer - por favor, preguntale a tu coach! A veces las cosas no van bien y que es mejor pedir ayuda a alguien con más experiencia. \ No newline at end of file diff --git a/es/python_introduction/README.md b/es/python_introduction/README.md new file mode 100755 index 00000000000..eceeacaaac9 --- /dev/null +++ b/es/python_introduction/README.md @@ -0,0 +1,733 @@ +# Introducción a Python + +> Parte de este capítulo se basa en tutoriales por Geek Girls Carrots (http://django.carrots.pl/). + +Vamos a escribir algo de código! + +## Python prompt + +Para empezar a jugar con Python, tenemos que abrir una *línea de comandos* en nuestra computadora. Ya sabes cómo hacerlo, lo aprendiste en el capítulo de [Introducción a la línea de comandos][1]. + + [1]: /intro_to_command_line/README.html + +Una vez que estés listo, sigue las siguientes instrucciones. + +Queremos abrir una consola de Python, así que escribe `python3` y pulsa Enter. + + $ python3 + Python 3.4.2 (...) + Type "copyright", "credits" or "license" for more information. + >>> + + +## Tu primer comando en Python! + +Después de ejecutar el comando de Python, el cursor cambia a `>>>`. Para nosotros esto significa que por ahora sólo podemos utilizar comandos en el lenguaje Python. No tienes que escribir en `>>>`-Python lo hará por ti. + +Si deseas salir de la consola de Python en cualquier momento, simplemente escribe `exit()` o usar el atajo `Ctrl + Z` para Windows y `Ctrl + D` para Mac/Linux. Entonces no verás `>>>`. + +Pero ahora, no queremos salir de la consola de Python. Queremos aprender más sobre él. Vamos a empezar con algo muy simple. Por ejemplo, trata de escribir algo de matemáticas, como `2 + 3` y pulsa Enter. + + >>> 2 + 3 + 5 + + +Bien! ¿Ves como salió la respuesta? Python sabe matemáticas! Podrías intentar otros comandos como: - `4 * 5` - `5 - 1` - `40 / 2` + +Diviértete con esto por un tiempo y luego vuelve aquí :). + +Como puedes ver, Python es una gran calculadora. Si te estás preguntando qué más puede hacer... + +## Strings + +¿Y tu nombre? Escriba tu nombre de pila en frases como ésta: + + >>> "Ola" + 'Ola' + + +Ahora has creado tu primer string! Es un conjunto de caracteres que pueden ser procesadas por una computadora. La cadena debe comenzar y terminar con el mismo carácter. Esto puede ser comillas simples (`'`) o dobles (`"`) - Python dice que lo que esta dentro de ellas es un string(texto). + +Las cadenas pueden ser concatenadas. Prueba esto: + + >>> "Hola alli " + "Ola" + 'Hola alli Ola' + + +También puedes multiplicar las cadenas con un número: + + >>> "Ola" * 3 + 'OlaOlaOla' + + +Si necesitas poner un apóstrofe dentro de tu cadena, tienes dos maneras de hacerlo. + +Usar comillas dobles: + + >>> "Runnin' down the hill" + "Runnin' down the hill" + + +o escapa el apóstrofo con una barra invertida (``): + + >>> 'Runnin\' down the hill' + "Runnin' down the hill" + + +Bien, ¿eh? Para ver tu nombre en letras mayúsculas, simplemente escribe: + + >>> "Ola".upper() + 'OLA' + + +Usaste la **función** `upper` en tu cadena! Una función (como `upper()`) es un conjunto de instrucciones que Python tiene que realizar a un objeto determinado (`"Ola"`) una vez que se llama. + +Si quisieras saber el número de letras que contiene tu nombre, también existe una función para esto. + + >>> len("Ola") + 3 + + +Te preguntarás porque a veces se llama a las funciones con un `.` al final de un string (p. ej. `"Ola".upper()`), y a veces primero se llama a una función y se coloca el string entre paréntesis. Bueno, en algunos casos las funciones pertenecen a objetos, como `upper()`, que pueden solo ser utilizadas en strings (cadena de caracteres) En este caso, llamamos a la función de un **método**. Otra veces, las funciones no pertenecen a ninguno especifico y pueden ser usados en diferentes objetos, como `len()`. Eso es porque estamos dando `"Ola"` cono un parámetro a la función `len`. + +### Resumen + +Ok, suficiente de strings. Hasta ahora has aprendido sobre: + +* **la terminal** - teclea comandos (código) dentro de la terminal de Python para obtener resultados en preguntas en Python +* **números y strings** - en Python los números son usados para matemáticas y strings para objetos de texto +* **operadores** - como + y *, combinan valores para producir uno nuevo +* **funciones** como upper() y len(), realizan opciones sobre los objetos. + +Estos son los conocimientos básicos que puedes aprender de cualquier lenguaje de programación. ¿Listo para algo un poco más fuerte? ¡Apostamos que lo estás! + +## Errores + +Intentemos con algo nuevo. ¿Podríamos obtener la longitud de un número de la misma manera que obtuvimos la longitud de nuestro nombre? Teclea `len(304023)` y presiona Enter: + + >>> len(304023) + Traceback (most recent call last): + File "", line 1, in + TypeError: object of type 'int' has no len() + + +Tenemos nuestro primer error! Dice que los objetos de tipo "int" (números enteros) no tienen ninguna longitud. ¿Qué podemos hacer ahora? Quizás podemos escribir el numero como un string. Strings tienen longitud, ¿cierto? + + >>> len(str(304023)) + 6 + + +¡Funcionó! Utilizamos la función `str` dentro de la función `len` . `str()` convierte todo a strings. + +* La función `str` convierte cosas en **strings** +* La función `int` convierte cosas en **integers** + +> Importante: podemos convertir números en texto, pero no podemos necesariamente convertir texto en números - ¿qué sería de `int('hello')`? + +## Variables + +Un concepto importante en programación son las variables. Una variable no es más que un nombre para alguna cosa que tu puedes usar más tarde. Los programadores usan estas variables para almacenar datos, hacer su código más legible y así no tener que seguir recordando que hace cada cosa. + +Supongamos que queremos crear una nueva variable llamada `nombre`: + + >>> name = "Ola" + + +¿Ves? ¡Es fácil! Es simplemente: name equivale a Ola. + +Como te has dado cuenta, el programa no regresa algo como lo hacia antes. Entonces, ¿Cómo sabemos que la variable existe realmente? Simplemente introduce `name` y pulsa Enter: + + >>> name + 'Ola' + + +Súper! La primera variable :). Siempre podrás cambiar lo que se refiere a: + + >>> name = "Sonja" + >>> name + 'Sonja' + + +Puedes usarla dentro de las funciones: + + >>> len(name) + 5 + + +¿Increíble, cierto? Por supuesto, las variables pueden ser cualquier cosa, también números! Prueba esto: + + >>> a = 4 + >>> b = 6 + >>> a * b + 24 + + +Pero ¿qué pasa si usamos el nombre equivocado? ¿Puedes adivinar qué pasaría? Vamos a probar! + + >>> name = "Maria" + >>> names + Traceback (most recent call last): + File "", line 1, in + NameError: name 'names' is not defined + + +Un error! Como puedes ver, Python tiene diferentes tipos de errores y estos se llaman **NameError**. Python te dará este error si intenta utilizar una variable que no ha sido definida aún. Si más adelante te encuentra con este error, verifica tu código para ver si es que no haya ningún nombre. + +Juega con esto por un rato y mira que puedes hacer! + +## La función print + +Intenta esto: + + >>> name = 'Maria' + >>> name + 'Maria' + >>> print(name) + Maria + + +Cuando sólo se escribe `name`, el intérprete de Python responde con la *representación* de la variable 'name', que es las letras M-a-r-i-a, rodeadas de comillas simples ''. Cuando dices `print(name)`, Python va a "Imprimir" el contenido de la variable a la pantalla, sin las comillas, que es mejor. + +Como veremos después, print() también es útil cuando queremos imprimir cosas dentro de las funciones, o bien cuando queremos imprimir cosas en múltiples lineas. + +## Listas + +Entre string e integers, Python tiene todo tipo de diferentes tipos de objetos. Ahora vamos a introducir una llamada **list**. Las listas son exactamente lo que piensas que son: son objetos que son listas de otros objetos :) + +Adelante y crear una lista: + + >>> [] + [] + + +Sí, esta lista está vacía. No es muy útil, ¿verdad? Vamos a crear una lista de números de la lotería. No queremos repetirlos todo el tiempo, así que lo pondremos en una variable, también: + + >>> lottery = [3, 42, 12, 19, 30, 59] + + +Muy bien, tenemos una lista! ¿Qué podemos hacer con él? Vamos a ver cuántos números de la lotería. ¿Tienes alguna idea de función que debe usar para eso? Ya sabes esto! + + >>> len(lottery) + 6 + + +¡ Sí! `Len()` puede dar un número de objetos en una lista. ¿Wow, verdad? Tal vez lo resolvamos ahora: + + >>> lottery.sort() + + +Esto no devuelve nada, sólo cambia el orden en que los números aparecen en la lista. Vamos a imprimir otra vez y ver que pasó: + + >>> print(lottery) + [3, 12, 19, 30, 42, 59] + + +Como puedes ver, los números en la lista ahora están ordenados de menor a mayor. ¡ Felicidades! + +¿Tal vez queremos invertir ese orden? Vamos a hacerlo! + + >>> lottery.reverse() + >>> print(lottery) + [59, 42, 30, 19, 12, 3] + + +Fácil, verdad? Si quieres añadir algo a tu lista, puedes hacerlo escribiendo este comando: + + >>> lottery.append(199) + >>> print(lottery) + [59, 42, 30, 19, 12, 3, 199] + + +Si desea mostrar sólo el primer número, puede hacerlo mediante el uso de **indixes**. Un index es el numero que se muestra en una lista como una ocurrencia. La computadora inicia la cuenta en 0, así que el primer objeto en la lista es en el índice 0, el siguiente es 1, y así sucesivamente. Intenta esto: + + >>> print(lottery[0]) + 59 + >>> print(lottery[1]) + 42 + + +Como puedes ver, puedes acceder a diferentes objetos en la lista utilizando el nombre de la lista y el índice del objeto dentro de corchetes. + +Para diversión adicional, prueba algunos otros índices: 6, 7, 1000, -1, -6 ó -1000. A ver si se puede predecir el resultado antes de intentar el comando. ¿Tienen sentido los resultados? + +Puedes encontrar una lista de todos los métodos disponibles de la lista en este capítulo de la documentación de Python: https://docs.python.org/3/tutorial/datastructures.html + +## Diccionarios + +Un diccionario es similar a una lista, pero accedes a valores mediante una llave en lugar de un índice. Una llave puede ser cualquier cadena o número. La sintaxis para definir un diccionario vacío es: + + >>> {} + {} + + +Esto demuestra que acabas de crear un diccionario vacío. ¡Hurra! + +Ahora, trata de escribir el siguiente comando (trata de reemplazando tu propia información): + + >>> participant = {'name': 'Ola', 'country': 'Poland', 'favorite_numbers': [7, 42, 92]} + + +Con este comando, que acaba de crear una variable denominada `participante` con tres pares de clave y valor: + +* El `name` apunta al valor `'Ola'` (un objeto `string`), +* `country` apunta a `'Poland'` (otro `string`), +* y `favorite_numbers` apunta a `[7, 42, 92]` (una `list` con tres números en el). + +Puedes verificar el contenido de llaves individuales con esta sintaxis: + + >>> print(participant['name']) + Ola + + +Mira, es similar a una lista. Pero no necesitas recordar el índice - sólo el nombre. + +¿Qué pasa si pedimos a Python el valor de una llave que no existe? ¿Puedes adivinar? ¡Pruébalo y verá! + + >>> participant['age'] + Traceback (most recent call last): + File "", line 1, in + KeyError: 'age' + + +¡Mira, otro error! Este es un **KeyError**. Python es de ayuda y te dice que la llave `'age'` no existe en este diccionario. + +¿Cuándo utilizar un diccionario o una lista? Bueno, eso es un buen punto para reflexionar. Sólo ten una solución en mente antes de mirar la siguiente respuesta. + +* ¿Sólo necesitas una secuencia ordenada de elementos? Usa una lista. +* ¿Necesita asociar valores claves, así que puedas consultarlos eficientemente (por llaves) más adelante? Utiliza un diccionario. + +Diccionarios, parecen listas, son *mutables*, lo que significa que pueden ser cambiados después de ser creados. Puedes agregar nuevos pares clave-valor en el diccionario después de que se crea, ejemplo: + + >>> participant['favorite_language'] = 'Python' + + +Como listas, método en los diccionarios, `len()` devuelve el número de pares clave-valor en el diccionario. Adelante, escribe el comando: + + >>> len(participant) + 4 + + +Espero tenga sentido hasta ahora. :) ¿Lista para más diversión con los diccionarios? Salta a la siguiente línea para algunas cosas sorprendentes. + +Puedes utilizar el comando `del` para borrar un elemento en el diccionario. Si deseas eliminar la entrada correspondiente a la clave `'favorite_numbers'`, sólo tienes que escribir el siguiente comando: + + >>> del participant['favorite_numbers'] + >>> participant + {'country': 'Poland', 'favorite_language': 'Python', 'name': 'Ola'} + + +Como puedes ver en la salida, el par de clave y valor correspondiente a la tecla de 'favorite_numbers' ha sido eliminado. + +Además, también puedes cambiar un valor asociado a una clave ya creada en el diccionario. Teclea: + + >>> participant['country'] = 'Germany' + >>> participant + {'country': 'Germany', 'favorite_language': 'Python', 'name': 'Ola'} + + +Como puedes ver, el valor de la clave `'country'` ha sido alterado de `'Poland'` a `'Germany'`. :) ¿Emocionante? ¡Hurra! Has aprendido otra cosa asombrosa. + +### Resumen + +Impresionante! Sabes mucho sobre programación ahora. En esta última parte aprendiste sobre: + +* **errors** - ahora sabe cómo leer y entender los errores que aparecen si Python no entiende un comando que has dado +* **variables** - nombres para los objetos que permiten codificar más fácilmente y hacer el código más legible +* **lists** - las listas de objetos almacenados en un orden determinado +* **dictionaries** - objetos almacenados como pares de clave y valor + +¿Emocionada por la siguiente parte? :) + +## Compara cosas + +Una gran parte de la programación incluye comparar cosas. ¿Qué es más fácil comparar? Números, por supuesto. Vamos a ver cómo funciona: + + >>> 5 > 2 + True + >>> 3 < 1 + False + >>> 5 > 2 * 2 + True + >>> 1 == 1 + True + + +Le dimos a Python algunos números para comparar. Como puedes ver, Python puede comparar no sólo números, pero también puede comparar resultados de método. Bien, ¿eh? + +¿Te preguntas por qué pusimos dos signos de igual `==` al lado del otro para comparar si los números son iguales? Utilizamos un solo `=` para asignar valores a las variables. Siempre, **siempre** es necesario poner dos `==` Si desea comprobar si las cosas son iguales entre sí. + +Dan a Python dos tareas más: + + >>> 6 >= 12 / 2 + True + >>> 3 <= 2 + False + + +`>` y `<` son fáciles, pero ¿qué es significa `> =` y `< =`? Se leen así: + +* x `>` y significa: x es mayor grande que y +* x `<` y significa: x es menor que y +* x `< =` y significa: x es menor o igual a y +* x `> =` y significa: x es mayor o igual a y + +¡Genial! ¿Quieres hacer uno mas? Intenta esto: + + >>> 6 > 2 y 2 < 3 + True + >>> 3 > 2 y 2 < 1 + False + >>> 3 > 2 ó 2 < 1 + True + + +Puedes darle a Python muchos números para comparar, y te dará una respuesta! Muy inteligente, verdad? + +* **and** - Si utilizas el operador `and`, las comparaciones deben estar en orden para que sea True +* **or** - Si utilizas el operador `or`, sólo una de las comparaciones tiene que ser verdadera para ser True + +¿Has oído la expresión "comparar manzanas con naranjas"? Vamos a probar el equivalente en Python: + + >>> 1 > 'django' + Traceback (most recent call last): + File "", line 1, in + TypeError: unorderable types: int() > str() + + +Aquí verás que al igual que en la expresión, Python no es capaz de comparar un número (`int`) y una string (`str`). En cambio, se muestra un **TypeError** y nos dice que no se puede comparar los dos tipos. + +## Boolean + +Por cierto, acabas de aprender acerca de un nuevo tipo de objeto en Python. Se llama un **boolean**--y es probable el más sencillo. + +Hay sólo dos objetos Boolean: - True - False + +Pero para que Python entender esto, es necesario siempre escribir como True (primera letra mayúscula, con el resto de la letra minúscula). **true, TRUE, tRUE no funcionan -- sólo True es correcto.** (Lo mismo aplica a False, por supuesto.) + +Valores booleans pueden ser variables, también! Ve aquí: + + >>> a = True + >>> a + True + + +También puedes hacerlo de esta manera: + + >>> a = 2 > 5 + >>> a + False + + +Practica y diviértete con booleanos corriendo los siguientes comandos: + +* `True and True` +* `False and True` +* `True or 1 == 1` +* `1 != 2` + +¡Felicidades! Los booleans son de las mejores funciones en la programación y acabas de aprender como usarlos. + +# ¡Guárdalo! + +Hasta ahora hemos estado escribiendo nuestro código de python en el intérprete, lo cual nos limita a una línea de código a la vez. Programas normales son guardados en archivos y ejecutados por el **intérprete** o **compiler** de nuestro idioma de programación. Hemos estado corriendo nuestros programas una linea a la vez en el **intérprete** de Python. Necesitaremos mas de una linea de código para las siguientes tareas, entonces necesitaremos hacer rápidamente lo siguiente: + +* Salir del intérprete de Python +* Abrir el editor de texto de nuestra elección +* Guardar algo de código en un nuevo archivo de python +* ¡Correrlo! + +Para salir del interprete de Python que hemos estado usando, simplemente escribe la función de ~~~ exit() ~~~: + + >>>exit() + $ + + +Esto te llevará de vuelta a la linea de comando. + +Anteriormente, elegimos un editor de código en la sección de [code editor][2]. Tendremos que abrir el editor ahora y escribir algo de código en un archivo nuevo: + + [2]: code_editor/README.md + + print('Hello, Django girls!') + + +Obviamente, ahora eres una desarrolladora Python muy experimentada, así que siéntete libre de escribir algún código que has aprendido hoy. + +Ahora tenemos que guardar el archivo y asignarle un nombre. Vamos a llamar al archivo **python_intro.py** y guárdalo en tu escritorio. Podemos nombrar el archivo de cualquier manera que queramos, lo importante aquí es asegurarse que el archivo finalice con **.py**, esto indica nuestro ordenador que este es un **archivo ejecutable de Python**. + +Con el archivo guardado, es hora de ejecutarlo. Utilizando las habilidades que has aprendido en la sección de línea de comandos, utiliza la terminal para **cambiar los directorios** al escritorio. + +En un Mac, el comando se verá algo como esto: + + cd /Users//Desktop + + +En Linux, va a ser así (la palabra "Desktop" puede ser traducido a su idioma): + + cd /home//Desktop + + +Y en windows, será así: + + cd C:\Users\\Desktop + + +Si te quedas atascada, sólo pide ayuda. + +y luego usa Python para ejecutar el código en el archivo como este: + + $ python3 python_intro.py + Hello, Django girls! + + +Muy bien! Ejecutaste tu primer programa de Python. ¿Se siente increíble? + +Ahora puedes moverte a una herramienta esencial en la programación: + +## If...elif...else + +Un montón de cosas en el código sólo son ejecutadas cuando se cumplen las condiciones. Por eso Python tiene algo llamado **sentencias if**. + +Reemplace el código en el archivo **python_intro.py** por esto: + + if 3 > 2: + + +Si guardamos y ejecutams, veríamos un error como este: + + $ python3 python_intro.py + File "python_intro.py", line 2 + ^ + SyntaxError: unexpected EOF while parsing + + +Python da más instrucciones para lo que se suponen se ejecutará si la condición `3 > 2` resulta ser verdadera (o `True` para el caso). Intentemos hacer Python print "¡ funciona!". Cambiar tu código en el archivo **python_intro.py** a esto: + + if 3 > 2: + print('It works!') + + +¿Observa cómo nos hemos puesto una sangría en la siguiente línea de código por 4 espacios? Tenemos que hacer esto para que Python sepa que el código resulta ser verdad. Puedes hacer un espacio, pero casi todos los programadores Python hacen 4 para hacerlo más legible. Una solo Tab también contará como 4 espacios. + +Guarda y ejecútalo de nuevo: + + $ python3 python_intro.py + It works! + + +### ¿Qué pasa si no? + +En ejemplos anteriores, el código fue ejecutado sólo cuando las condiciones eran ciertas. Pero Python también tiene declaraciones `elif` y `else`: + + if 5 > 2: + print('5 is indeed greater than 2') + else: + print('5 is not greater than 2') + + +Cuando esto se ejecute imprimiría: + + $ python3 python_intro.py + 5 is indeed greater than 2 + + +Si 2 fuera un número mayor que 5, entonces el segundo comando sería ejecutado. Fácil, verdad? Vamos a ver cómo funciona `elif`: + + name = 'Sonja' + if name == 'Ola': + print('Hey Ola!') + elif name == 'Sonja': + print('Hey Sonja!') + else: + print('Hey anonymous!') + + +y ejecutado: + + $ python3 python_intro.py + Hey Sonja! + + +¿Ves lo que pasó ahí? + +### Resumen + +En los últimos tres ejercicios aprendiste acerca de: + +* **comparando cosas** - en Python puedes comparar cosas mediante el uso de `>`, `> =`, `==`, `< =`, `<` y las `y` los operadores `o` +* **Boolean** - un tipo de objeto que sólo puede tener uno de dos valores: `True` o `False` +* **Guardar archivos** - almacenar código en archivos y puede ejecutar programas más grandes. +* **si... elif... else** - las sentencias permiten ejecutar código sólo cuando se cumplan ciertas condiciones. + +Sigue la última parte de este capítulo. + +## Tus propias funciones! + +¿Recuerdas las funciones como `len()` que puedes ejecutar en Python? Buenas noticias, aprenderás cómo escribir tus propias funciones ahora! + +Una función es un conjunto de instrucciones que deben ser ejecutadas en Python. Cada función en Python comienza con la palabra clave `def`, se asigna un nombre y puede tener algunos parámetros. Vamos a empezar con algo fácil. Reemplace el código en **python_intro.py** con lo siguiente: + + def hi(): + print('Hi there!') + print('How are you?') + + hi() + + +Bien, nuestra primera función está lista! + +Te preguntarás por qué hemos escrito el nombre de la función en la parte inferior del archivo. Esto es porque Python lee el archivo y ejecuta desde arriba hacia abajo. Así que para poder utilizar nuestra función, tenemos que escribirla en la parte inferior. + +Hay que ejecutar esto y ver lo que sucede: + + $ python3 python_intro.py + Hi there! + How are you? + + +Eso fue fácil! Vamos a construir nuestra primera función con parámetros. Utilizaremos el ejemplo anterior - una función que dice 'Hi' a la persona - con un nombre: + + def hi(name): + + +Como puedes ver, ahora dimos a nuestra función un parámetro que llamamos `name`: + + def hi(name): + if name == 'Ola': + print('Hi Ola!') + elif name == 'Sonja': + print('Hi Sonja!') + else: + print('Hi anonymous!') + + hi() + + +Como puedes ver, teníamos que poner dos guiones antes de la función `print`, porque `if` necesita saber lo que debe ocurrir cuando se cumple la condición. Vamos a ver cómo funciona: + + $ python3 python_intro.py + Traceback (most recent call last): + File "python_intro.py", line 10, in + hi() + TypeError: hi() missing 1 required positional argument: 'name' + + +Ops, un error. Por suerte, Python nos da un mensaje de error bastante útil. Nos dice que la función `hi()` tiene un argumento requerido `(name)` y que se nos olvidó pasarlo al llamar a la función. Vamos a arreglarlo en la parte inferior del archivo: + + hi("Ola") + + +y otra vez: + + $ python3 python_intro.py + Hi Ola! + + +¿Y si cambiamos el nombre? + + hi("Sonja") + + +y ejecutamos: + + $ python3 python_intro.py + Hi Sonja! + + +Ahora ¿qué crees que pasará si escribes otro nombre allí? (No Ola o Sonja) Prueba y verás si tienes razón. Esto debe imprimir: + + Hi anonymous! + + +Esto es increíble, ¿verdad? Así no tienes que repetirlo cada vez que deseas cambiar el nombre de la persona. Y eso es exactamente por qué necesitamos funciones - para no repetir tu código! + +Vamos a hacer algo más inteligente - hay más de dos nombres, y escribir una condición para cada uno sería difícil, ¿no? + + def hi(name): + print('Hi ' + name + '!') + + hi("Rachel") + + +Ahora vamos a llamar al código: + + $ python3 python_intro.py + Hi Rachel! + + +¡Felicidades! Acabas de aprender cómo escribir funciones :) + +## Loops + +Ya es la última parte. ¿Eso fue rápido, verdad? :) + +Como hemos mencionado, los programadores son perezosos, no les gusta repetir. Programación es automatizar las cosas, así que no queremos saludar a cada persona por su nombre manualmente, ¿verdad? Es ahí donde los ciclos son muy útil. + +¿Todavía recuerda las listas? Hagamos una lista de las chicas: + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + + +Queremos saludar a todas ellas por su nombre. Tenemos la función `Hi` que hace eso, así que vamos a usarlo en un ciclo: + + for name in girls: + + +La sentencia ~ ~ ~ for ~ ~ ~ se comporta de manera similar a la sentencia ~ ~ ~ if ~ ~ ~, ve el código a continuación ambos necesitan ser ident a cuatro espacios. + +Aquí está el código completo que estará en el archivo: + + def hi(name): + print('Hi ' + name + '!') + + girls = ['Rachel', 'Monica', 'Phoebe', 'Ola', 'You'] + for name in girls: + hi(name) + print('Next girl') + + +y cuando lo eejcutamos: + + $ python3 python_intro.py + Hi Rachel! + Next girl + Hi Monica! + Next girl + Hi Phoebe! + Next girl + Hi Ola! + Next girl + Hi You! + Next girl + + +Como puedes ver, se repetirá todo lo que pones dentro de una instrucción `for` con una sangría para cada elemento de la lista de `girls`. + +También puedes usar `for` en números usando el método `range`: + + for i in range(1, 6): + print(i) + + +Lo cual imprime: + + 1 + 2 + 3 + 4 + 5 + + +`range` es una función que crea una lista de números en serie (estos números son proporcionados por ti como parámetros). + +Ten en cuenta que la segunda de estas dos cifras no está incluida en la lista que es de salida en Python (significado `range(1, 6)` cuenta desde 1 a 5, pero no incluye el número 6). + +## Resumen + +Eso es todo. **Eres totalmente genial!** Esto realmente no fue tan fácil, así que deberías sentirte orgullosa de ti misma. Estamos definitivamente orgullosos de que hayas llegado hasta aquí! + +Agarra un cupcake y vamos al siguiente capítulo :) + +![Cupcake][3] + + [3]: images/cupcake.png \ No newline at end of file diff --git a/es/python_introduction/images/cupcake.png b/es/python_introduction/images/cupcake.png new file mode 100644 index 00000000000..fa2f3baeae6 Binary files /dev/null and b/es/python_introduction/images/cupcake.png differ diff --git a/es/template_extending/README.md b/es/template_extending/README.md new file mode 100755 index 00000000000..46d2f000033 --- /dev/null +++ b/es/template_extending/README.md @@ -0,0 +1,118 @@ +# Extendiendo Plantillas + +Otra cosa buena que Django tiene para tí es la **extensión de plantillas** ¿Qué significa esto? Significa que puedes usar las mismas partes de tu HTML en diferentes páginas de tu sitio. + +De esta manera no tienes que repetir lo mismo en cada archivo, cuando quieras usar la misma información/layout. Y si quieres cambiar algo,no tienes que hacerlo en cada plantilla, ¡solo una vez! + +## Creando una plantilla base + +Una plantilla base es la más básica de las plantillas que quieras extender en cada página de tu sitio. + +Vamos a crear un archivo `base.html` en `blog/templates/blog/`: + + blog + └───templates + └───blog + base.html + post_list.html + + +Luego abrelo y copia todo de `post_list.html` al archivo `base.html`, de la siguiente manera: + + {% load staticfiles %} + + + Django Girls blog + + + + + + + + + +
+
+
+ {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} +
+
+
+ + + + +Luego en `base.html`, remplaza completamente tu `` (todo entre `` and ``) con esto: + + + +
+
+
+ {% block content %} + {% endblock %} +
+
+
+ + + +Nosotros básicamente remplazamos todo entre `{% for post in posts %}{% endfor %}` con: + + {% block content %} + {% endblock %} + + +¿Qué significa esto? Acabas de crear un `block`, el cual es una etiqueta de plantilla que te permite insertar HTML en este bloque en otros templates que extiendan de `base.html`. Te mostraremos como hacer esto en un momento. + +Ahora guardalo, y abre `blog/templates/blog/post_list.html` de nuevo. Elimina todo lo demás que está dentro del body y luego elimina ``, de forma que el archivo se vea de la siguiente manera: + + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} + + +Y ahora agrega esta linea al inicio del archivo: + + {% extends 'blog/base.html' %} + + +Significa que ahora estamos extendiendo del template `base.html` en `post_list.html`. Solo nos falta una cosa: poner todo (excepto la línea que acabamos de agregar) entre `{% block content %}` y `{% endblock content %}`. Como esto: + + {% extends 'blog/base.html' %} + + {% block content %} + {% for post in posts %} +
+
+ {{ post.published_date }} +
+

{{ post.title }}

+

{{ post.text|linebreaks }}

+
+ {% endfor %} + {% endblock content %} + + +¡Eso es todo! Verifica que tu sitio web aún funcione apropiadamente :) + +> Si tienes un error `TemplateDoesNotExists` que diga que no hay un archivo `blog/base.html` y tienes `runserver` ejecutandose en la consola, intenta pararlo (presionando Ctrl+C - Botones Control y C juntos) y reinicialo ejecutando el comando `python manage.py runserver`. \ No newline at end of file diff --git a/es/whats_next/README.md b/es/whats_next/README.md new file mode 100755 index 00000000000..121d072be84 --- /dev/null +++ b/es/whats_next/README.md @@ -0,0 +1,40 @@ +# ¿Qué sigue? + +Felicitaciones! **Eres increible**. Estamos orgullosos! <3 + +### ¿Qué hacer ahora? + +Toma un descanso y relajate. Acabas de hacer algo realmente grande. + +Después de eso, asegúrate de: + +* Seguir a Django Girls en [Facebook][1] o [Twitter][2] para estar al día + + [1]: http://facebook.com/djangogirls + [2]: http://twitter.com/djangogirls + +### ¿Me puede recomendar cualquier recurso adicional? + +¡Sí! En primer lugar, sigue adelante y prueba nuestro libro llamado [Django Girls Tutorial: Extensiones][3]. + + [3]: http://djangogirls.gitbooks.io/django-girls-tutorial-extensions/ + +Más adelante, puedes intentar los recursos enumerados a continuación. Todos muy recomendados! + +- [Django's official tutorial][4] +- [New Coder tutorials][5] +- [Code Academy Python course][6] +- [Code Academy HTML & CSS course][7] +- [Django Carrots tutorial][8] +- [Learn Python The Hard Way book][9] +- [Getting Started With Django video lessons][10] +- [Two Scoops of Django: Best Practices for Django book][11] + + [4]: https://docs.djangoproject.com/en/1.7/intro/tutorial01/ + [5]: http://newcoder.io/tutorials/ + [6]: http://www.codecademy.com/en/tracks/python + [7]: http://www.codecademy.com/tracks/web + [8]: http://django.carrots.pl/en/ + [9]: http://learnpythonthehardway.org/book/ + [10]: http://gettingstartedwithdjango.com/ + [11]: http://twoscoopspress.org/products/two-scoops-of-django-1-6