Taller Introductorio
autor: | Martín Gaitán |
---|---|
evento: | Atica / iSummit 2012 |
lugar: | Loja, Ecuador |
fecha: | Lunes 22 de octubre, 2012 |
Mini introduccion a Python
Micro introducción a "la web"
Introducción a Django
- Ideas generales
- Modelos
- Admin
- Vistas
- URLs
- Templates
- Formularios
A veces hablo mucho. :-/
Este material está basado en trabajos de
Bajo licencias Creative Commons by-sa
¡Gracias!
El canónico "Python es un gran primer lenguaje" suscitó "¡Python es un gran último lenguaje!"
—Noah Spurrier
Si no me dedicara al fútbol programaría Python
—Lionel Messi
Contestemos esa pregunta!
$ python Python 2.7.3 (default, Aug 1 2012, 05:14:39) [GCC 4.6.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>>
$ ipython Python 2.7.3 (default, Aug 1 2012, 05:14:39) Type "copyright", "credits" or "license" for more information. IPython 0.13 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. In [1]:
In [1]: 10 + 4 Out[1]: 14 In [2]: saludo = 'Ubyn Ybwn!' In [3]: print saludo.decode('rot13') # que sucede? In [4]: import this # y esto?
Python trae potentes estructuras de datos built-in
- Listas: contenedor ordenado de objectos
- Tuplas: simil a listas pero inmutables
- Diccionarios: mapas clave-valor
- Conjuntos: objetos unicos, no ordenado
- y más!
>>> a = [100, 'huevos', 'sal'] >>> a [100, 'huevos', 'sal'] >>> a[0] 100 >>> a[-2:] ['huevos', 'sal'] >>> a + ['oro', 9] [100, 'huevos', 'sal', 'oro', 9] >>> a[0] = "manteca" >>> a ['manteca', 'huevos', 'sal']
>>> dias = {"Ene": 31, "Jul": 30} >>> dias {'Ene': 31, 'Jul': 30} >>> dias["Ene"] 31 >>> dias["Ago"] = 31 >>> dias["Jul"] = 31 >>> dias {'Ago': 31, 'Ene': 31, 'Jul': 31} >>> "Mar" in dias False >>> dias.keys() (['Ago', 'Ene', 'Jul'] >>> dias.values() [31, 31, 31])
>>> conjunto = {'Loja', 3, 3 } >>> conjunto set([3, 'Loja']) >>> 'Loja' in conjunto True >>> conjunto.intersection({3}) set([3]) >>> conjunto.difference({3}) set(['Loja'])
>>> bichos = ["pulgas", "piojos"] >>> for bich in bichos: ... print "Mata-" + bich ... Mata-pulgas Mata-piojos
if <expresion>: <suite> elif <expresion>: <suite> else: <suite>
Abrir un editor (gedit, por ejemplo) y escribir una función
def alcuadrado(n): res = n ** 2 return res print alcuadrado(3)
Guardarlo como cuadrado.py y ejecutarlo:
$ python cuadrado.py
def potenciar(n, exp=2): res = n ** exp return res >>> potenciar(2, 3) 8 def oracion(quien, que="corre", como="lento"): return "%s %s %s" % (quien, que, como) >>> oracion("El conejo", como="veloz") 'El conejo corre veloz'
>>> elemento1, elemento2 = dos_elementos = ('Hola', 5) >>> dos_elementos ('Hola', 5) >>> elemento2 5
>>> [num**2 for num in range(10) if num % 2 == 0] [0, 4, 16, 36, 64]
Python es modular y tiene espacios de nombre
- Un .py es un módulo.
- Un directorio con __init__.py es un paquete
>>> from cuadrado import alcuadrado >>> alcuadrado(1j) (-1+0j)
# posicion.py import math # baterias incluídas! class Posicion(object): def __init__(self, x, y): self.x = x self.y = y def distancia(self): """La hipotenusa. Pitágoras programaba Python""" x = self.x**2 + self.y**2 return math.sqrt(x)
>>> import posicion # importa todo el módulo >>> p1 = posicion.Posicion(3, 4) >>> p1.x 3 >>> p1.dist() 5.0 >>> p2 = posicion.Posicion(7, 9) >>> p2.y 9 >>> p1.y 4
class PosicionRect(Posicion): """ Sistema sin diagonales """ def distancia(self): return float(self.x + self.y) >>> p1 = PosicionRect(3, 4) >>> p1.dist() 7.0
class Posicion(object): ... def __unicode__(self): return u'(%.2f, %.2f)" % (self.x, self.y) >>> print p1 u'(3.00, 4.00)'
Vayamos a la web!
Mediante métodos, cabecera y parámetros (datos). Importantes:
Código, Cabecera y Datos
200 OK, 404 Not Found
Hypertext Transfer? Ahora es cualquier cosa!
Modelos
Definición y manejo de los datos. (Crear, Modificar, Guardar, etc)
Vistas
Lógica de la aplicación. Reacciona con HTTP
Templates
Visualización de la información
Objetivo: un sitio para manejar tickets (bugs, por ejemplo)
Lo llamaremos
"La Tiquetera"
Descargar: tiquetera.zip desde http://bit.ly/tiquetera
¿A Qué llama Django un Proyecto?
Conjunto de aplicaciones y configuraciones para un sitio en particular
$ django-admin.py startproject tiquetera
Y qué es una Aplicación ?
- Una aplicación web que hace una tarea en particular (weblog, encuesta, etc)
- Un proyecto puede tener muchas apps.
- Una aplicación puede ser parte de distintos proyectos (son pluggables)
- Hay muchisimas apps listas para usar! djangopackages.com
$ cd tiquetera $ django-admin.py startproject tiquetera
django-admin.py y manage.py:
./manage.py help [comando]
El archivo settings.py:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'db.sqlite', ... INSTALLED_APPS = ( ... 'django.contrib.admin', 'tiquetera.tickets',)
Requerimientos
# models.py from django.db import models from django.contrib.auth.models import User ESTADOS = (('AB', 'Abierto'), ('CE', 'Cerrado'), ('CU', 'En curso')) class Ticket(models.Model): titulo = models.CharField(max_length=150) descripcion = models.TextField() autor = models.ForeignKey(User) fecha_creacion = models.DateTime(auto_now_add=True) asignado_a = models.ForeignKey(User, null=True, blank=True) estado = models.CharField(max_length=2, choices=ESTADOS)
$ python manage.py syncdb
$ python manage.py sqlall tickets BEGIN; CREATE TABLE "tickets_ticket" ( "id" integer NOT NULL PRIMARY KEY, "titulo" varchar(150) NOT NULL, "descripcion" text NOT NULL, "autor_id" integer NOT NULL REFERENCES "auth_user" ("id"), "fecha_creacion" datetime NOT NULL, "asignado_a_id" integer REFERENCES "auth_user" ("id"), "estado" varchar(2) NOT NULL ) ; CREATE INDEX "tickets_ticket_32ec34e8" ON "tickets_ticket" ("autor_id"); CREATE INDEX "tickets_ticket_4a1d037a" ON "tickets_ticket" ("asignado_a_id"); COMMIT;
$ python manage.py shell
>>> from tiquetera.tickets.models import Ticket >>> from django.contrib.auth.models import User >>> usuario = User.objects.all()[0] >>> Ticket.objects.all() []
>>> Ticket.objects.create( titulo='Un bug', descripcion='Bug de prueba', autor=usuario, estado='AB')>>> Ticket.objects.filter(autor=usuario) [ticket] >>> t = Ticket.objects.filter(titulo__contains='bug')[0] >>> t.titulo 'Un bug'
Interfaz ABM (CRUD)
# admin.py import models from django.contrib import admin class TicketAdmin(admin.ModelAdmin): date_hierarchy = 'fecha_creacion' list_display = ('__unicode__', 'autor', 'asignado_a', 'fecha_creacion', 'proyecto', 'estado' ) list_display_links = ('proyecto', ) list_editable = ('asignado_a', 'estado') list_filter = ('proyecto__nombre', 'estado') search_fields = ['id', 'titulo', 'descripcion'] admin.site.register(Ticket, TicketAdmin)
$ python manage.py runserver
Y vamos en el navegador a
Vistas
def listar_tickets(request): tickets = Ticket.objects.all() return render(request, "ticket_listar.html", { "tickets": tickets })
def detalle_ticket(request, id): ticket = Ticket.objects.get(id=id) return render(request, "ticket_detalle.html", { "ticket": ticket })
urls.py relaciona direcciones con vistas
urlpatterns = patterns('', url(r'^$', 'tiquetera.tickets.views.listar_tickets', name='ticket-listado'), url(r'^ticket/(?P<id>\d+)/$', 'tiquetera.tickets.views.detalle_ticket', name='ticket-detalle'), url(r'^admin/', include(admin.site.urls)), )
<h1>Listado de Tickets</h1> <ul> {% for ticket in lista_tickets %} <li> <a href="{{ ticket.get_absolute_url }}"> {{ ticket.title|upper }} </a> </li> <p>{{ ticket.descripcion|truncatewords:"15" }}</p> {% endfor %} </ul>
{% block nombre_bloque %}
Porción que puede redefinirse
{% extends 'template_base.html' %}
Herencia
{% include 'pedacito.html' %}
Incrustar fragmentos
from django import forms class ContactForm(forms.Form): asunto = forms.CharField(max_length=100) mensaje = forms.CharField() remitente = forms.EmailField() cc_a_mi = forms.BooleanField(required=False) >>> mi_form = ContactForm() >>> mi_form.as_p() >>> mi_form.is_valid() # no porque está vacío! >>>
if request.method == "POST": form = ContactForm(request.POST) if form.is_valid(): # aqui usamos los datos validos # que están en form.cleaned_data # Ejemplo: mandamos el email return redirect(...) else: form = ContactForm() return render(request, "contact.html", { "form": form, })
from django import forms from models import Ticket class TicketForm(forms.ModelForm): class Meta: model = Ticket
¡Nos vemos el miércoles!
Mientras tanto
http://github.com/mgaitan/curso-django
Y sumense a PyAr! Serán bienvenid@s
- http://www.python.org.ar
- Via IRC: #pyar en freenode.net
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |