Curso Django: Entendiendo como trabaja Django
La semana pasada vimos lo fácil que fue crear un proyecto y ejecutarlo en unos cuantos pasos, sin embargo esa simplicidad debe ir acompañada de una fuerte lógica para poder aplicar Django a proyectos reales, es por eso que esta semana nos dedicaremos a entender como es que Django hace toda esa magia.
[tipexperto titulo = “Nota”]Para tener una estupenda experiencia con Django, el orden de los archivos y directorios deben respetarse, caso contrario el caos llegará rápidamente a nuestro proyecto y fracasará al momento de hacerlo crecer con mas personas o requerimientos.[/tipexperto]
Antes de iniciar con la explicación de como funciona Django, dale un vistazo a este vídeo:
[youtube http://www.youtube.com/watch?v=c6JLEsXhEEc&feature=youtu.be]
Ahora que ya entiendes el contexto, empezamos!
MTV y Django
Se podría clasificar a Django como parte de la tercera generación del desarrollo web:
Sin embargo más alla de las clasificaciones que podrían existir, está el entender como funciona realmente, al entenderlo se puede llegar a dominarlo.
Al principio del curso de Django, les dije que era un framework MTV (una modificación de MVC, nada que ver con música), esto se debe a que los desarrolladores no tuvieron la intención de seguir algún patron de desarrollo, sino hacer el framework lo más funcional posible.
Para empezar a entender MTV debemos fijarnos en la analogía con MVC.
- El modelo en Django sigue siendo modelo
- La vista en Django se llama Plantilla (Template)
- El controlador en Django se llama Vista
Una imagen nos hará entender mejor esta relación:
Veamos que hace cada uno de ellos con un poco más de detalle y algunos conceptos adicionales.
El modelo
El modelo define los datos almacenados, se encuentra en forma de clases de Python, cada tipo de dato que debe ser almacenado se encuentra en una variable con ciertos parámetros, posee métodos también. Todo esto permite indicar y controlar el comportamiento de los datos.
La vista
La vista se presenta en forma de funciones en Python, su propósito es determinar que datos serán visualizados, entre otras cosas más que iremos viendo conforme avanzamos con el curso. El ORM de Django permite escribir código Python en lugar de SQL para hacer las consultas que necesita la vista. La vista también se encarga de tareas conocidas como el envío de correo electrónico, la autenticación con servicios externos y la validación de datos a través de formularios. Lo mas importante a entender con respecto a la vista es que no tiene nada que ver con el estilo de presentación de los datos, sólo se encarga de los datos, la presentación es tarea de la plantilla.
La plantilla
La plantilla es básicamente una página HTML con algunas etiquetas extras propias de Django, en si no solamente crea contenido en HTML (también XML, CSS, Javascript, CSV, etc).
Por ahora nos enfocaremos a lo básico el HTML. La plantilla recibe los datos de la vista y luego los organiza para la presentación al navegador web. Las etiquetas que Django usa para las plantillas permiten que sea flexible para los diseñadores del frontend, incluso tiene estructuras de datos como if, por por si es necesaria una presentación lógica de los datos, estas estructuras son límitadas para evitar un desorden poniendo cualquier tipo de código Python.
Esto permite que la lógica del sistema siga permaneciendo en la vista.
La configuración de las rutas
Django posee un mapeo de URLs que permite controlar el despliegue de las vistas, esta configuración es conocida como URLConf. El trabajo del URLConf es leer la URL que el usuario solicitó, encontrar la vista apropiada para la solicitud y pasar cualquier variable que la vista necesite para completar su trabajo. El URLConf esta construido con expresiones regulares en Python y sigue la filosofia de Python: Explicito es mejor que implícito. Este URLConf permite que las rutas que maneje Django seán agradables y entendibles para el usuario.
Si consideramos al URLConf en el esquema anterior tendríamos este resultado más completo.
Los archivos predeterminados
Otra parte importante es entender el propósito de los archivos que se crean de manera predeterminada, estos son:
Archivos del proyecto
- __init__.py: Este es un archivo vacío que le dice a Python que debe considerar este directorio como un paquete de Python. Si se desea saber más, se puede consultar la documentación sobre los paquetes.
- manage.py: Este archivo contiene una porción de código que permite interactuar con el proyecto de Django de muchas formas. Si se desea mayor detalle se encuentra la documentación oficial con respecto a manage.py.
- settings.py: Este archivo contiene todas las configuraciones para el proyecto, la documentación al respecto puede darnos mas detalles de la configuración de un proyecto en Django.
- urls.py: Contiene las rutas que están disponibles en el proyecto, manejado por URLConf, los detalles completos como siempre en la documentación oficial nos da mas detalles sobre las urls y Django.
Archivos de la aplicación
- __init__.py: La misma descripción anterior (líneas arriba).
- models.py: En este archivo se declaran las clases del modelo.
- views.py: En este archivo se declaran las funciones de la vista.
- test.py: En este archivo se declaran las pruebas necesarias para la aplicación, para mayor detalle sobre las pruebas y Django se puede consultar la documentación del proyecto.
Una vez que tenemos claro el funcionamiento básico de Django, desarrollemos un ejemplo dentro del proyecto que iniciamos la semana pasada, para experimentar por nuestra cuenta.
Modelo, Vista y Plantilla en 15 minutos
Antes de continuar, deben entender que esto solamente es un pequeño ejemplo, el modelo, vista y plantillas serán desarrolladas a detalle en las próximas semanas. Si existen dudas del porque de las instrucciones, estas serán resueltas a detalle en los siguientes capítulos. Si eres muy impaciente siempre tienes a disposición la documentación oficial del proyecto.
Nuestro proyecto debe tener una estructura similar a esta:
Tendremos que manejar para este proyecto 6 archivos:
- models.py (ya existe dentro de la carpeta principal).
- views.py (ya existe dentro de la carpeta principal).
- admin.py (aún no existe, pero estará dentro de la carpeta principal).
- urls.py (ya existe dentro de la carpeta recetario).
- settings.py (ya existe dentro de la carpeta recetario).
- lista_bebidas.html (aún no existe, estará dentro de una carpeta en la carpeta recetario).
models.py
Al principio models.py luce asi:
Usamos nuestro editor de texto favorito para editar models.py y redactamos lo siguiente:
from django.db import models class Bebida(models.Model): nombre = models.CharField(max_length=50) ingredientes = models.TextField() preparacion = models.TextField() def __unicode__(self): return self.nombre
views.py
views.py luce así al principio:
Igualmente con nuestro editor favorito abrimos views.py y lo dejamos de la siguiente forma:
from principal.models import Bebida from django.shortcuts import render_to_response def lista_bebidas(request): bebidas = Bebida.objects.all() return render_to_response('lista_bebidas.html',{'lista':bebidas})
admin.py
Este archivo no existe, así que lo creamos manualmente dentro de nuestro directorio de la aplicación, en este caso dentro del directorio principal. Lo debemos dejar de esta manera:
from principal.models import Bebida from django.contrib import admin admin.site.register(Bebida)
urls.py
Este archivo ya existe, se encuentra dentro del directorio recetario, así que lo único que debemos hacer es modificarlo para dejarlo de la siguiente manera:
from django.conf.urls import patterns, include, url from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', url(r'^$','principal.views.lista_bebidas'), url(r'^admin/doc/', include('django.contrib.admindocs.urls')), url(r'^admin/', include(admin.site.urls)), )
settings.py
Este archivo lo modificamos la semana pasada, se encuentra dentro de recetario. Debemos buscar la directiva TEMPLATE_DIRS (Debe encontrarse en la línea 113 aproximadamente). Debemos dejar esta sección de esta forma:
TEMPLATE_DIRS = ( os.path.join(RUTA_PROYECTO,'plantillas'), )
En esta sección le estamos diciendo que debe buscar las plantillas dentro de la carpeta del proyecto, en una carpeta llamada plantillas, como esta carpeta aún no existe debemos crearla manualmente dentro de recetario.
lista_bebidas.html
Este archivo no existe, lo crearemos manualmente dentro de la carpeta plantillas (si, esa que acabas de crear dentro de recetario).
Debes finalizar con una estructura similar a esta:
Una vez creado le ponemos la etiquetación HTML que nos permita visualizar la lista de bebidas. Podría quedarse de esta manera:
<!DOCTYPE html> <html lang='es'> <head> <title>Lista de bebidas de ejemplo</title> <meta charset='utf-8'> </head> <body> <h1>Recetario de Bebidas</h1> {% for elemento in lista %} <ul> <li><strong>{{elemento.nombre}}</strong></li> <li>{{elemento.ingredientes}}</li> <li>{{elemento.preparacion}}</li> </ul> {% endfor %} </body> </html>
Nota: Python es sensible a las mayúsculas y minúsculas
Poner en funcionamiento todo
Listo, tenemos todo listo para ver funcionando nuestro ejemplo, para ello debemos de sincronizar nuevamente nuestra base de datos, para ello, nos ubicamos en la carpeta principal del proyecto (aquella donde se encuentra el archivo manage.py). Una vez en la carpeta principal, desde una terminal digitamos:
python manage.py syncdb
Esto nos dará el siguiente resultado: (prestar atención a la segunda línea que nos indica la creación de una nueva tabla):
Una vez realizado esto, lanzamos nuestro servidor de desarrollo:
python manage.py runserver
Nos ubicamos en http://127.0.0.1:8000/admin, ingresamos con nuestros datos configurados en la primera vez que sincronizamos la base de datos (si no recuerdas los datos que pusiste, puedes borrar el archivo recetario.db y volver a digitar: python manage.py syncdb para resincronizar).
Una vez dentro de la interfaz administrativa veremos: (notar que aparece una opción Bebidas).
Podemos seguir intuitivamente la interfaz e ingresar datos:
Una vez guardados podemos ir a http://127.0.0.1:8000/ y veremos lo que acabamos de ingresar. De esta manera ya tienes una interfaz rápida de ingreso y visualización de datos.
Hay muchos puntos que en este capítulo he tenido que tocar superficialmente, esto no debe preocuparte, porque en los siguientes capítulos desarrollaré a detalle esos puntos, deseo recordarte que el objetivo de este pequeño ejemplo, es disfrutar la experiencia de la velocidad de Django, para el desarrollo de aplicaciones.
Si desean ver los archivos oficiales del proyecto, no olviden que pueden acceder al repositorio del mismo en github. Los datos de acceso para la interfaz administrativa del ejemplo del repositorio son los siguientes:
- usuario:sergio
- clave:maestros
La próxima semana tendremos el capítulo dedicado a El Modelo. Muchas gracias por sus comentarios en el capítulo anterior, eso enriquece mucho más cada capítulo.
excelente ya realice la este parte del tutorial gracias a @neosergio @maestros por el tutorial
Muy bueno! Claro y conciso!
Estaré a la espera del próximo!
Disculpa pero cual es la diferencia entre el modelo MVC y el modelo MTV, viendolo es practicamente igual pero cambiandole el nombre…
Para los puristas Django no encaja en el MVC, si bien es cierto tiene el mismo principio de separación por capas, la terminología no es la correcta y es por ello que los desarrolladores de Django prefieren llamar a la capa de presentación de datos como plantilla ya que no se trata de como se vean los datos, sino que datos se veran, por ello usar el termino plantilla brinda un sentido mas apropiado para lo que Django en si hace. En palabras simples las vistas en Django describen la información “que” se va a presentar y dejan a las plantillas la labor del “como” se van a presentar. El controlador en Django sería en si el propio framework. Existe un FAQ sobre ello en la propia documentación de Django que puedes revisar para aclarar tu duda: https://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names
Me gusta mucho django ! es algo mas que MTV creo que la forma en como lo estructuraron y la vision que tuvo con el concepto DRY
Por cierto la diferencia de MTV y MVC es muy clara ! y como dice Sergio lo pueden leer el el url que les paso, saludos a todos y disfruten django.
Gracias Sergio Infante. Estare atento a tu siguiente Clase
Muchas gracias Sergio, por el Curso.
A la hora de poner en marcha todo, por alguna razon que desconozco no me genera la tabla principal_bebidas. ¿Cúal sera la razón? :-s
Esto me sale:
DatabaseError at /
no such table: principal_bebida
Request Method: GET
Request URL: http://127.0.0.1:8000/
Django Version: 1.4
Exception Type: DatabaseError
Exception Value:
no such table: principal_bebida
Exception Location: C:\Python27\lib\site-packages\django\db\backends\sqlite3\base.py in execute, line 337
Python Executable: C:\Python27\python.exe
Python Version: 2.7.2
Python Path:
[‘C:\\Proy\\aprender’,
‘C:\\Windows\\system32\\python27.zip’,
‘C:\\Python27\\DLLs’,
‘C:\\Python27\\lib’,
‘C:\\Python27\\lib\\plat-win’,
‘C:\\Python27\\lib\\lib-tk’,
‘C:\\Python27’,
‘C:\\Python27\\lib\\site-packages’]
Server time: Lun, 30 Abr 2012 12:50:17 -0500
Gracias de antemano.
Que madre tanto que quiero aprender y no le entiendo Nada….!
Sergio I.M. que me recomiendas hacer tengo una aplicacion donde lleno datos y todo eso pero estoy llenando o mejor dicho quiero llenar una informacion, en la cual voy a incluir los datos del usuario que ingresa dichos datos valga la redundancia. Que tengo que hacer??, pense en usar el registro de session de usuarios del mismo django desde el auth importar hacer algunas truquitos con esto y pude jalar los datos. Lo que no me percate es que esto lo puedo hacer solo si inicio sesion en el centro de administracion de django. Es decir si cierro mi aplicacion no puedo jalar las sesiones y coger el dato del usuario que inicion session. Tengo que usar el cache o como podria hacerlo, agradeceria que me ayudaras en esto ya que es lo unico que me falta hacer :3
Eso me parece que es un error del nombre que usaste en el modelo y que no sincronizo como debería ser, puedo ayudarte a solucionarlo usando teamviewer, mandame un DM por Twitter para coordinar
Es muy simple, con paciencia. El curso lo estoy detallando de tal forma que se pueda seguir sin complicaciones. Si no entiendes porque tienes que escribir esas líneas pueda ser porque aún no entiendas muy bien Python para ello sigue la guía Python (http://www.maestrosdelweb.com/guias/#guia-python). Si ya sabes Python, los próximos capítulos se encargan de resolver tus dudas.
Django tiene todo un sistema de autenticación de usuarios (https://docs.djangoproject.com/en/dev/topics/auth/) y que no está amarrado al centro de administración. Quizas al leer esta parte de la documentación podría resolver muchas de las dudas que tienes.
Me falto mencionar que el capítulo nueve tratará sobre eso.
Seguro que ejecutaste el comando -python manage.py syncdb- el error es que no consigue la tabla. Saludos
Gracias por tomarte tu tiempo en responder, la verdad se agradece, ya resolvi el problema, fue un error de parte mia, en Aplicaciones instaladas en ves de agregar “principal”, agregue “recetario”. Muchas gracias Sergio, un saludo desde Tabasco, Mexico, adelante, y muchas gracias de nuevo.
Muy buen curso!!! En espera de la proxima entrega. Saludos!!!
Muchas gracias amigo Sergio I.M, por compartir tus conocimientos, capitulo tras capitulo me gusta mas Django, tuve problemas para hacer que la aplicación funcionara pero, después de algo de paciencia pude corregir el error. Esperando con ansias el próximo capitulo.
Creo que es porque escribiste mal termina en bebidas no bebida
Gracias por este cursi Sergio, al fin uno que no sea una simple traduccion de la documentacion de django. Se me hace que va un poco lento el curso pero a lo mejor es por que ya he leido varias veces todo esto (tambien se que un buen curso no se puede hacer a la carrera).
Un saludo y gracias por tu trabajo.
Con dedicación veras que Django al principio puedes tardar en aprender, pero despues será dificil que no lo aprecies
Muchas gracias , estoy tratando de hacer el curso muy didáctico, y resolver dudas de manera personal si es posible. Estos dos primeros capítulos son básicos, luego viene algo más interesante. El curso es para principiantes también y quizas es por ello que de repente si ya conoces Django, se te haga repetitivo.
Excelente tutorial, estoy empezando a seguir este desde la semana anterior; me parece un gran aportazo desde maestros del web.
Hmmm gracias Sergio I M leyendo la documentacion y un poco de ingenio logre hacer lo que queria con una linea de codigo. !! Mas bien una pregunta, como puedo hacer para jalar los nombres de los ManytoManyField y los ForeignKeyField???
y si olvido mi clave de admin? xD
no puedo ver la lista de capítulos desde firefox…
Gracias por compartir conocimiento. Esperando por el resto del curso. Muchísimas Gracias.
El próximo lunes toca ese tema ya falta poco
Si olvidas tu clave puedes: 1. Eliminar la base de datos y resincronizar, en el caso del curso sería borrar el archivo recetario.db 2. Usar django-admin.py changepassword 3. Crear un nuevo super usuario con django-admin.py createsuperuser. La documentación oficial del framework te puede ayudar https://docs.djangoproject.com/en/dev/ref/django-admin/
La lista de capítulos se encuentra aquí http://www.maestrosdelweb.com/editorial/curso-django-introduccion/. La próxima semana ya debe funcionar el enlace que esta en está página con los capítulos (aún no esta disponible)
Muy buen curso, espero que los siguientes capítulos estén pronto publicados.
Pero… ¿a qué viene el video? ¿qué aporta? si aporta algo interesante digan el minuto porque es excesivo.
El video aporta mucho para entender el contexto del desarrollo web actual, si eres impaciente debes ir al minuto 43 con 35 segundos y verlo desde ahí.
Gracias para compartir este curso
Sergio, muchísimas gracias por este curso, ya que tiene todos los ingredientes que se necesitan para comenzar con django (y en la ultima versión), Simplemente espectacular te felicito.
Gracias Martin
muy bueno el curso! y gracias por la paciencia. tengo un problemilla nomas cuando hago el runserver y entro en http://127.0.0.1:8000/admin/ me aparece
SyntaxError at /admin/
invalid syntax (views.py, line 7)
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/
Django Version: 1.4
Exception Type: SyntaxError
Exception Value:
invalid syntax (views.py, line 7)
Exception Location: C:\Python27\lib\site-packages\django\utils\importlib.py in import_module, line 36
Python Executable: C:\Python27\python.exe
Python Version: 2.7.3
Python Path:
[‘C:\\Users\\Danitelo\\Desktop\\Python\\recetario’,
‘C:\\Windows\\system32\\python27.zip’,
‘C:\\Python27\\DLLs’,
‘C:\\Python27\\lib’,
‘C:\\Python27\\lib\\plat-win’,
‘C:\\Python27\\lib\\lib-tk’,
‘C:\\Python27’,
‘C:\\Python27\\lib\\site-packages’]
ya me anda, me falto cerrar parentesis al archivo views.py
Hola Sergio, sigo atento a los cursos, tengo una gran duda con respecto a la organización de un proyecto.
Según entiendo la filosofía de Django recomienda tener un sistema en muchas aplicaciones en vez de todo en una sola, ahora bien.
Si quiero tener en mi proyecto un sistema de admin un blog y la pagina de la compañia ¿Como organizo las apps? , Si siguiera la filosofía tendría un montón de carpetas y estos 3 “modulos” mezclados, me gustaría saber como organizar las apps por carpetas por ejemplo
mi_proyecto
manage.py
mi_proyecto
settings.py
….
Apps
Blog
Admin
Home
Esto es correcto o es mejor tener en la raiz todas las aplicaciones de todos los “modulos”? ¿Cual es la mejor estructura de carpetas para un proyecto a largo plazo separando por modulos?
Gracias
Lo mejor es tener las carpetas de las aplicaciones en la raiz, puesto que te permite reutilizarlas sin complicarse por la organización interna de subcarpetas
La verdad que muy bueno sigue este curso rapido 😉 Gracias
Por que la interfaz en el navegador me sale muy plana es decir, muy básica, sin formato.
Gracias excelente curso.
Alguna referencia adicional o quizas una captura de pantalla??. Puedo suponer que el “sin formato” te refieres a que te muestra solo HTML, eso es porque Django es un framework que funciona del lado del servidor. No es un CMS, no es una plantilla, no es Dreamweaver.
Hola sergio, excelente curso, pero tengo algunos problemas:
1.- cuando utilizo en la plantilla {{elemento.nombre}} , no se muestran los datos, están en blanco, estoy sobre Windows – XP , el admin funciona perfectamente, puedo ingresar varios datos pero cuando veo en el browser (distintos – explorer o chrome) no visualizo los datos de la base
2.- Que hosting recomiendas para hacer algunos ejemplos , ideal algo gratis, estoy utilizando alwaysdata.com, pero tengo que hacer una configuración, manual que se complica, para utilizar Django.
Hola Roberto. Dale un vistazo al repositorio del proyecto, y comprueba que todos los archivos esten como los tuyos. (http://neosergio.github.com/recetario_mdw/).
Con respecto al hosting, el capitulo de despliegue que vendra en las próximas semanas resolverán por completo tus dudas.
Tengo un pequeño problema en crear la tabla de bebidas; he repetido el proceso muchas veces y revisado pero todo esta igual ?
Exelente tutorial me ayudado a comprender como funciona Django de una manera mucho mas clara y practica
agredeceria la solucion a mi problema
puede que el error sea que no guardastes el archivo HTML (lista_bebidas.html) dentro de la carpeta templates, a mi me paso y estuve 10 minutos mirando como loco y fue que guarde el archivo html en otra ruta sin darme cuenta. ¡Un saludo!
Muy bueno! consulta:Tendrán un link similar para desarrollo de aplicaciones para iphone ?
Hola @Boris, lanzamos la guía iOs5, para que revises el contenido y te sirva de ayuda: http://www.maestrosdelweb.com/guias/#manual-iphone
Saludos.
hola me sale esto cuando intento dentrar al servidor:
ImportError en / admin
No se puede importar el nombre de Bebida
Solicitud de método: GET
Solicitud de URL: http://127.0.0.1:8000/admin
Django Versión: 1.4
Tipo de excepción: ImportError
Excepción de valor:
No se puede importar el nombre de Bebida
Excepción Ubicación: C: \ proyecto \ demo \ director \ admin.py en , la línea 1
Python ejecutable: C: \ \ Python27 python.exe
Python Versión: 2.7.3
Python Ruta de acceso:
[‘C: \ \ proyecto \ \ demo’,
‘C: \ \ WINDOWS \ \ system32 \ \ python27.zip’,
‘C: \ \ Python27 \ \ DLLs’,
‘C: \ \ Python27 \ \ lib’,
‘C: \ \ Python27 \ \ lib \ \ plat-win’,
‘C: \ \ Python27 \ \ lib \ \ lib-tk’,
‘C: \ \ Python27’,
‘C: \ \ Python27 \ \ lib \ \ site-packages’]
Horario del servidor: Miércoles, 18 de julio 2012 22:11:57 -0500
por favor ayudemen no se que puede ser e intentado barias cosas y no me funciona
Hola Sergio, Seguí esta parte de tu tutorial y me surgió el siguiente problema, resulta que la interfaz administrativa y todo marcha como la seda, asi como almacenar los objetos en la base de datos, mi problema está al desplegarlos por que cuando pongo http://127.0.0.1:8000
aparece solamente el titulo de la pagina lista_bebidas.html, y no la lista correspondiente…
EXCELENTE!!! me encanta #django
Hola, felicitaciones por el curso, esta muy bueno y estoy aprendiendo mucho, tengo un problema al ejecutar syncdb no me crea la tabla que indicas en la imagen y cuando corro el servidor me da el siguiente error:
ViewDoesNotExist at /admin/
Could not import principal.views.lista_bebidas. View does not exist in module principal.views.
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/
Django Version: 1.4
Exception Type: ViewDoesNotExist
Exception Value:
Could not import principal.views.lista_bebidas. View does not exist in module principal.views.
Exception Location: /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/django/core/urlresolvers.py in get_callable, line 101
Python Executable: /Library/Frameworks/Python.framework/Versions/2.7/Resources/Python.app/Contents/MacOS/Python
Python Version: 2.7.2
yo al archivo views.py lo tengo tal cual lo escribiste no se porque me dice que no existe. Desde ya muchas gracias.
Gracias por compartir tu conocimiento, yo no tengo ningun conocimiento de python y django pero de a poco voy incursionando. se agradece la forma que tenes de explicar, que para alguien que no tiene conocimientos de django como yo, puedo seguirte. un abrazo enorme desde argentina, y mucha luz
Sergio,
Gracias por tu tiempo de compartir el excelente material, estoy aprendiendo sobre python y django en castellano!
saludos