113
1 INTRODUCCIÓN A DJANGO JOSÉ SÁNCHEZ MORENO Created: 2016-09-16 vie 12:43

INTRODUCCIÓN A DJANGO - o2w.es es un helper con opciones para crear proyectos y apps. ... 'django.contrib.staticfiles', 'polls',) Contiene las aplicaciones que carga django. 3.6

Embed Size (px)

Citation preview

1

INTRODUCCIÓN ADJANGO

JOSÉ SÁNCHEZ MORENOCreated: 2016-09-16 vie 12:43

2 . 1

1 DJANGO

2 . 2

1.0.1 DJANGO

Framework de desarrollo web de servidor muy potente.

Escrito en pythonEstilo MVCNombrado así en alusión a Django Reinhardt(guitarrista de jazz)Creado en 2005 para gestionar sitios de noticiasonline.Bajo licencia BSD

2 . 3

1.0.2 QUIEN USA DJANGO

La NASA crea las webs en django.PinterestInstagramTodas las webs de mozilla (disponibles en github)Muchas webs de google (las hace potato)The Washington PostThe GuardianTicketeaetc…

2 . 4

1.0.3 ESTÁ COMPUESTO POR

Modelos (ORM)Vistas (Views)Plantillas (Templates)Formularios (Forms)AdminMiddlewaresGestión de cache

2 . 5

1.0.4 MÁS

i18n (internacionalización) y i10n (localización)LoggingEmailsRssPaginaciónMensajes

2 . 6

1.0.5 MÁS

SesionesSerializaciónSitemapsGestión de ficheros estáticosValidación de datosTipos genéricosSeñales…

2 . 7

1.0.6 ESTRUCTURA BÁSICA

Con�guraciónArchivo o archivos en los que se define laconfiguración

UrlsSe usa uno principal que se especifica en el settings.

ModelosDefinen nuestros modelos de la base de datos.

VistasContienen la lógica

TemplatesLa capa de presentación

2 . 8

1.0.7 URLS

Con el archivo de urls lo que hacemos es vincular las urlsa acciones, o sea a vistas (views).

my_app/urls.py

urlpatterns = [ url(r'̂download/(?P<uuid>[\w]+)/$', views.download, name='download'), url(r'̂', include('web.urls')), url(r'̂ckeditor/', include('ckeditor.urls')), url(r'̂admin/', include(admin.site.urls)),]

2 . 9

1.0.8 MODELOSEjemplo de modelo, normalmente en models.py

class Log(models.Model): tarea = models.ForeignKey(Tarea, null=True, blank=True) accion = models.ForeignKey(Accion, null=True, blank=True) para = models.CharField(null=True, blank=True, max_length=255) asunto = models.CharField(null=True, blank=True, max_length=255)

def __str__(self,): return "Tarea {} - para {} - {}".format(self.tarea, self.para, self.asunto)

Los modelos son clases en python que modelan algo delmundo real. Estos modelos persisten en una base de

datos.

2 . 10

1.0.9 TEMPLATES

Normalmente desde las vistas:

Vamos a acceder a los modelos de la base de datosusando el orm.Con los datos obtenidos creamos lo que se llama uncontextoRenderizamos html con el template y la informacióndel contextoDevolvemos el html en un HttpResponse

2 . 11

1.0.10 EJEMPLO DE PLANTILLAS_base.html

<!DOCTYPE html>{% load static %}<html lang="es"> <head> <link href="{% static "css/main.css" %}" type="text/css"> </head> <body> {% block body %}{% endblock %} </body></html>

index.html

{% extends '_base.html' %}{% block body %}<h1>Hola mundo</h1>{% endblock %}

2 . 12

1.0.11 VISTAS

Las vistas son clases o funciones que devuelven unhttpResponse, normalmente con html.

2 . 13

1.0.12 EJEMPLOS DE VISTASEjemplo de una vista que usa Class Base View

class EnlacesView(ListView): template_name = '_enlaces.html' model = Enlaces

class IndexView(TemplateView): template_name = 'index.html'

enlaces = EnlacesView.as_view()index = IndexView.as_view()

Ejemplo de otra con un decorador.

@render_to('map.html')def map(request): country = request.GET.get('country', '') countries = models.Country.objects\ .filter(name__in=['IRELAND', 'N IRELAND', 'UK']) return { 'countries': countries, 'selected_country': country }

2 . 14

1.0.13 EJEMPLO DE VISTAEjemplo de una vista que descarga un pdf

class DownloadView(DetailView): model = Url slug_field = 'uuid' slug_url_kwarg = 'uuid'

def get_object(self,): obj = super(DownloadView, self).get_object() return obj.get_object()

def get(self, request, *args, **kwargs): obj = self.get_object() response = HttpResponse(content_type='application/pdf') response['Content-Disposition'] = 'attachment; filename="descarga.pdf"' response.write(obj.get_pdf() return response

download = DownloadView.as_view()

urls.py para la vista anterior

from . import viewsurlpatterns = [ url(r'̂download/(?P<uuid>[\w]+)/$', views.download, name='download'),]

2 . 15

1.0.14 BASES DE DATOS EN DJANGO

PostgresLa bd recomendada, la mejor soportada en django.

Mysqlbien soportada

SQLiteEmpleada para tests o entornos de desarrollomayormente.

OracleVersión 11.2 y superior

2 . 16

1.0.15 ORM

El orm abstrae las consultas de de sql. Esto nos damuchas ventajas … y algunos inconvenientes.

Al abstraer sql hacemos el código portable paracualquier base de datos.Conceptualmente es más fácil de manejar.Trabajas con términos relacionados con el dominio dela aplicación.

2 . 17

1.0.16 EJEMPLOSQueryset devuelve una secuencia de modelos de tipo servicio.

queryset = Servicio.objects\ .no_programados\ .ignorar_gruas_de_traslados\ .no_tareas\ .no_salidas_de_base\ .filter(pendiente=False)\ .filter(anulado=False)\ .exclude(fecha_localizacion__isnull=True)

if condicion: queryset = queryset.exclude(excluido=True)

2 . 18

1.0.17 EJEMPLOSModificamos el servicio y guardamos los datos en la bd.

servicio = Servicio.objects.first()servicio.excluido = Trueservicio.save()

Creamos un servicio

servicio = Servicio.objects.create(nombre="Prueba", fecha=timezone.now(), pendiente=True)

3 . 1

2 INSTALACIÓNPara instalar django normalmente se usa virtualenv.

Es una especie de contenedor que hace que laslibrerías se instalen dentro del directorio indicado. Asípodemos tener diferentes versiones de una librería envarios proyectos.

Creación de un un virtualenv e instalamos django

# Creamosvirtualenv .

# Activamossource bin/activate

# Instalamos appspip install django==1.10.1

3 . 2

2.0.1 REQUIREMENTS

Por convención se usa un archivo en el raíz del proyectodónde se especifican los requerimientos del mismos

requirements.txtel archivo requirements.txt contiene las dependencias de la aplicación.

django==1.7.3djangocms-admin-styledjangorestframework==2.4.4

Es aconsejable especificar las versiones

Se instalan usando pip install -r requirements.txt

3 . 3

2.0.2 CREACIÓN DE UN PROYECTO

Una vez que hemos instalado django usandorequirements o pip install django, podemos usar

django-admin es un helper con opciones para crear proyectos y apps.

django-admin startproject miapp .

Esta instrucción nos creará una estructura de directoriossimilar a esta.Estructura de un proyecto

manage.pymiapp/├── __init__.py├── settings.py├── urls.py└── wsgi.py

3 . 4

2.0.3 SETTINGS

Bastante complejo y largo, lo bueno es que se parecerábastante en muchos proyectos.

3 . 5

2.0.4 INSTALLED_APPSUna variable importante es la que contiene las aplicaciones que carga django.

INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'polls',)

Contiene las aplicaciones que carga django.

3 . 6

2.0.5 DATABASESLa variable databases sirve para configurar las bases de datos, podemos tener varias.

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'principal', 'USER': 'root', 'PASSWORD': '', 'HOST': 'localhost', }, 'secundaria': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': 'secundaria', 'USER': 'user', 'PASSWORD': 'pass', 'HOST': '192.168.200.219', },}

Normalmente se controla el comportamiento con losrouters, también se puede manualmente.

3 . 7

2.0.6 OTROS

CACHESConfiguramos las caches, memcached o redis, etc.

DEBUGPara activar debug

LANGUAGE_CODELenguaje por defecto de la app

LANGUAGESLista de idiomas

MIDDLEWARE_CLASSESListado de clases que pueden modificar la petición ola respuesta.

ROOT_URLCONFArchivo dónde se configuran las urls.

3 . 8

2.0.7 ¿CÓMO EMPEZAR?

Pensar como la app va a interactuar con el exterior (lasurls).Definir los modelos de datos.Definir las vistas.Crear las plantillas.

3 . 9

2.0.8 POR DÓNDE EMPEZAR

Lo anteriormente comentado lo podemos encontrar enlos siguientes archivos

urls.pymodels.pyviews.pytemplates

4 . 1

3 MODELOSLos modelos son clases que son subclases dedjango.db.models.ModelCada atributo representa un campo de la base dedatos.

Ejemplo de un modelo con dos campos.

from django.db import models

class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30)

4 . 2

3.0.1 TIPOS DE CAMPOS MÁS USADOS (FIELDS)

BooleanFieldCharFieldDateField, DateTimeField, TimeFieldDecimalFieldEmailField y URLFieldFileField e ImageFieldFloatFieldIntegerFieldSlugFieldTextField

4 . 3

3.0.2 ESPECIFICOS PARA POSTGRESQL

ArrayFieldHStoreFieldJsonFieldRangefield

4 . 4

3.0.3 RELACCIONES

ForeignKeyRelaciones entre modelos (1 a n)

ManyToManyFieldRelacciones (m a n)

OneToOneFieldRelacción (1 a 1)

Ejemplo de uso de campos relacionales.

staff_member = models.ForeignKey(User, limit_choices_to={'is_staff': True})friends = models.ManyToManyField("self")user = models.OneToOneField(settings.AUTH_USER_MODEL)

4 . 5

3.0.4 MIGRACIONES

A partir de django 1.7 (antes south)Las migraciones, son la manera de propagar loscambios de los modelos en la base da datos. De estamanera, las bases de datos se van adaptandoautomáticamente a los cambios que ocurren en losmodelos.

5 . 1

3.1 USOComando que crea una migración (cambios o creación) para una aplicación.

./manage.py makemigrations [app]

Se usa para crear migraciones de los modelos de unaapp, es necesario especificarla se se trata de una appnueva que no tiene migraciones. Si ya tiene, y noespecificamos [app] se aplica a todas.

Aplica las migraciones que no están aplicadas a la base de datos.

./manage.py migrate [app]

Ejecuta las migraciones contra la base de datos. Sólolas que no se han procesado ya.

5 . 2

3.1.1 JUGAR CON EL MODELO

Usando el shellPodemos interactuar directamente con django a través del shell

./manage.py shell

Crear un 3 clientes nuevos.Buscar el cliente con más trabajadores.Darlo de baja (activo = False)

5 . 3

3.1.2 REPASO ORM

�lterFiltra

excludeFiltra excluyendo según las condiciones

create, delete, updateCreación, borrado, modificación

get, get_or_createObtiene una instancia, en el segundo caso si noexiste lo crea.

�rst, lastEl primero y último del queryset

5 . 4

3.1.3 REPASO ORM (2)

earliest, latestPrimero y último según campo especificado

existsDevuelve si existe la queryset

countDevuelve el total de instancias de modelo delqueryset

order_byOrdena queryset, "-campo" para inverso.

usingLa usamos si queremos que la queryset use otra dbdiferente a default

5 . 5

3.1.4 SE PUEDEN CREAR NUEVOS MÉTODOS PARA ELQUERYSET

Por defecto los modelos tienen un manager, podemoscambiarlo por otro creando nuevos métodos o usando

filtros por defecto.Ejemplo de creación de queryset personalizados.

class PersonQuerySet(models.QuerySet): def __init__(self): return super().__init__().filter(role__in=['A', 'E'])

def authors(self): return self.filter(role='A')

def editors(self): return self.filter(role='E')

class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor')))) objects = PersonQuerySet.as_manager()

5 . 6

3.1.5 EXPRESIONES DEL ORM

Son de la forma�eld__lookuptype=value

lookuptypes exact, iexact, contains, icontains, startwith,endwith, in, gt, gte, lt, lte, range, year, month, day,

week_day, hour, minute, second, isnull, search, regex,iregex

5 . 7

3.1.6 MODELOS RELACIONADOS

Se puede hacer búsquedas en los modelos relacionadosusando __

Por ejemplo, los clientes que tengan facturas con líneasde más de 100

Busqueda en tablas relacionadas a traves de ForeignKeyField, ManyToManyField, OneToOneField

Clientes.objects.filter(facturas__lineas__total__gte=100)

Facturas.objects.filter(lineas__descripcion="Servicio")

Facturas.objects.filter(lineas__servicio__codigo="1")

5 . 8

3.1.7 SQL EN EL ORM

Se pueden hacer consultas a la db usando sql. Podemoscombinar el orm con los modelos.

Devolvería instancias de Person con los datos de la consula.

>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):... print(p)John SmithJane Jones

5 . 9

3.1.8 EJECUTANDO SQL DIRECTAMENTE

Se puede obtener el cursor de la base de datos pararealizar consultas directas.

Se hace usando el PEP 0249, Database API, es la mismapara todas.

Ejecutando directamente sql

from django.db import connectionfrom django.db import connections

cursor = connection.cursor()cursor = connections["default"].cursor()

cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])

cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])row = cursor.fetchone()

6 . 1

4 URLSSon expresiones regulares.argumentos con nombre *(?P<arg>\d+) y sin nombre(\d+)Se pueden montar otras url usando include

Configuración de urls, normalmente my_app.urls.py

urlpatterns = [ url(r'̂$', main_views.homepage, name='home'), url(r'̂help/', include('apps.help.urls')),]

6 . 2

4.0.1 URLS (2)

Usamos nombres en las urls para referirnos a ellas:

Templates usando {% url %}Código usando django.core.urlresolvers.reverse()Desde el modelo usando get_absolute_url()

El tag url nos busca en las urls configuradas y nos devuelve la ruta

<a href="{% url 'news-year-archive' 2012 %}">2012 Archive</a>

Resolvemos la url en python

from django.core.urlresolvers import reversereturn HttpResponseRedirect(reverse('news-year-archive', args=(2012,)))

6 . 3

4.0.2 EJEMPLO REALEjemplo en la url principal montamos otras aplicaciones.

urlpatterns = [ url(r'̂i18n/', include('django.conf.urls.i18n')), url(r'̂accounts/', include('allauth.urls')), url(r'̂admin/', include(admin.site.urls)), url(r'̂', include('perfil.urls')), url(r'̂captcha/', include('captcha.urls')), url(r'̂actividades/', include('actividades.urls')), url(r'̂api/v1/', include('api.urls')), url(r'̂tests/', include('tests.urls')), url(r'̂comentarios/', include('django.contrib.comments.urls')), url(r'̂$', views.home, name="home"), url(r'̂sobre-nosotros/', include('sobre_nosotros.urls')), url(r'̂ayuda/', include('ayuda.urls')), url(r'̂colaboradores/', include('colaboradores.urls')), url(r'̂invitacion/', include('invitaciones.urls')), url(r'̂404/', TemplateView.as_view(template_name='404.html')), url(r'̂', include('cms.urls')), url(r'̂filer/', include('filer.urls')),]

7 . 1

5 VISTASPodemos crear vistas usando funciones o clases

Cada vista recibe un HttpRequest y devuelve unHttpResponse

7 . 2

5.0.1 FUNCIONES

Son funciones que reciben como primer parámetrorequest (HttpRequest) y devuelven un response

(HttpResponse).Vista básica

def vista(request): return HttpResponse("<h1>Mi Vista</h1>")

Estas son algunas funciones útiles para las vistas que sonfunciones.

Librería de atajos de django.

from django.shortcuts import render, render_to_response, redirect, get_object_or_404, get_list_or_404

7 . 3

5.0.2 CLASS BASED VIEWS

Es la evolución de las vistas para reutilizar más código.Definen comportamientos clásicos y nos permite

sustituir lo que necesitamos. Referencia: http://ccbv.co.uk/

TemplateViewRedirectViewListViewDetailViewFormViewCreateViewUpdateViewDeleteViewDe fechas

7 . 4

5.0.3 TEMPLATEVIEW

template_name / get_template_nameget_context_dataVista de plantilla la función get_context_data añade info a la plantilla.

class HomeView(TemplateView): template_name = "my_app/index.html"

def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context['number'] = random.randrange(1, 100) return context

home = login_required(HomeView.as_view())

7 . 5

5.0.4 REDIRECTVIEW

url / get_redirect_url()permanent

Redirige a /frontend

class HomeView(RedirectView): url = "/frontend/"

7 . 6

5.0.5 LISTVIEW

modelorderingpaginate_byqueryset / get_queryset()template_namecontext_object_name

7 . 7

5.0.6 EJEMPLO LISTVIEWLa plantilla por defecto es my_app/document_list.html podemos cambiarlo usando template_name

class DocumentList(ListView): model = Document paginate_by = 10

Muestra todos los Documentos de la página seleccionada y muestra el paginador.

{% extends '_base.htm' %}{% block body %} {% for item in object_list %} <p>{{item.name}}</p> <p>{{item.description}}</p> {% endfor %}

{% if page_obj %} {% bootstrap_paginate page_obj range=10 %} {% endif %}{% endblock %}

7 . 8

5.0.7 LISTVIEW: ¿QUÉ HACE EL CÓDIGO ANTERIOR?

Hace un queryset del modelo Document.objects.all()Pagina los resultados, selecciona la página segúnrequest.GET.get("page")Compone un context con object_list, page_obj, etcRenderizamos la plantilla my_app/document_list.htmlcon eso contextoDevuelve el resultado en un HttpResponse

7 . 9

5.0.8 DETAILVIEW

modelqueryset / get_queryset()pk_url_kwargslug_fieldslug_url_kwargtemplate_namecontext_object_name

7 . 10

5.0.9 DETAILVIEW: EJEMPLOUrl para configurar la vista

urlpatterns = [ url(r'̂documento/(?P<pk>\d+)/$', DocumentDetailView.as_view(), name='documento_detail')]

Selecciona el objecto, y renderiza en my_app/document_detail.html

class DocumentDetailView(DetailView): model = Document

Muestra el detalle del documento

{% extends '_base.htm' %}{% block body %} <p>{{object.name}}</p> <p>{{object.description}}</p>{% endblock %}

7 . 11

5.0.10 CREATEVIEW

context_object_namefieldsinitialmodelqueryset / get_queryset()pk_url_kwargslug_fieldslug_url_kwargtemplate_namecontext_object_name

7 . 12

5.0.11 CREATEVIEW: EJEMPLOVista de create view

class DocumentCreateView(CreateView):model = Documento fields = ['nombre', 'descripcion', 'archivo']

Mostramos el formulario dinámicamente generado a partir del modelo.

{% extends '_base.htm' %}{% block body %}<form action="" method="post">{% csrf_token %} {{ form.as_p }} <input type="submit" value="Crear documento" /></form>{% endblock %}

7 . 13

5.0.12 CREATEVIEW

Cuando es GET:

Genera el formulario dinámicamente a base delmodelo usando ModelFormRenderiza el formulario.

Cuando es POST:

Valida el formulario contra la especificación delmodelo.Si no es válido muestra el formulario con los erroresSi es válido guarda el objecto en la base de datos.Redirige a la url del objecto (si está definida).

7 . 14

5.0.13 UPDATEVIEW

Es practicamente igual que CreateView, pero con partede los mixins de DetailView para seleccionar el objeto a

editar

8 . 1

6 PLANTILLAS

8 . 2

6.0.1 TEMPLATE_CONTEXT_PROCESSORS

Son clases o funciones que añaden información alcontexto a la hora de renderizar las plantillas.Podemos añadir las nuestras si queremos añadir a lasplantillas nuestro contexto.'django.core.context_processors.auth','django.core.context_processors.debug','django.core.context_processors.i18n','django.core.context_processors.media',

8 . 3

6.0.2 ORIENTADAS A OBJETOS

extends, para extender de la plantilla padreblock para sustituir bloquesinclude para incluir otras plantillas

_base.html

<html lang="es"> <head> <title>{% block "title" %}My App{% endblock %}</title> {% block "extra_header" %}{% endblock %} </head> <body>{% block body %}{% endblock %}</body></html>

index.html

{% extends '_base.html' %}{% block title %}Título: Hola Mundo{% endblock %}{% block body %}<h1>Hola mundo</h1>{% endblock %}

8 . 4

6.0.3 DJANGO TEMPLATE LANGUAGE

tags{% nombre %}

tagsblock, comment, for, firstof, if, load, with, include, …

�ltros|filtro

�ltrosadd, capfirst, center, cut, floatformat, join, last, safe,…

8 . 5

6.0.4 TAGS Y FILTROS PERSONALIZADOS

Al poner {% load mistags %}

Busca en el módulo de todas las aplicacionesapps/templatetags/mistags.py

8 . 6

6.0.5 FILTROSCreación de un tag personalizado que podemos usar en las plantillas.

@register.filter(name='elimina')def elimina(value, arg): return value.replace(arg, '')

Como se usa el tag.

{% load mistags %}

{{ variable|elimina:","}}

8 . 7

6.0.6 TAGSEjemplo de creación de tags

@register.simple_tag(takes_context=True)def current_time(context, format_string): timezone = context['timezone'] return your_get_current_time_method(timezone, format_string)

@register.simple_tag(name='minustwo')def some_function(value): return value - 2

Ejemplo de uso

{% load mistags %}

{% current_time fecha %}{% minustwo 5 %}

8 . 8

6.0.7 INCLUSIÓN TAGS

Nos permiten reutilizar lógica y presentación.Definimos la plantilla a usar en el tag.

<ul>{% for book in books %} <li>{{ book.title }}</li>{% endfor %}</ul>

Definimos el tag y asignamos la plantilla

@register.inclusion_tag('book_snippet.html')def books_for_author(author): books = Book.objects.filter(authors=author) return {'books': books}

Usamos el tag, renderizaría la plantilla con el contexto generado en el tag.

{% load mistags %}{% books_for_author author %}

8 . 9

6.0.8 MÁS COMPLEJASPodemos crear tags que parseen nuestra propia sintaxis.

@register.tag(name="upper")def do_upper(parser, token): nodelist = parser.parse(('endupper',)) parser.delete_first_token() return UpperNode(nodelist)

class UpperNode(template.Node): def __init__(self, nodelist): self.nodelist = nodelist

def render(self, context): output = self.nodelist.render(context) return output.upper()

Ejemplo de uso

{% upper %} This will appear in uppercase, {{ user_name }}.{% endupper %}

9 . 1

7 ADMINISTRACIÓN DEDJANGO

Es una herramienta muy potente y compleja.

En nuestra aplicación, si queremos gestionar un modeloen el admin tenemos que hacer lo siguiente.

Ejemplo básico de uso de admin

from django.contrib import adminfrom .models import MiModelo

admin.site.register(MiModelo)

9 . 2

7.0.1 LOGIN EN EL ADMIN

Si ejecutamos.Comando para iniciar el servidor web de desarrollo de django

python manage.py runserver

Y abrimos el navegador en ,veremos que nos pide usuario y contraseña para entrar

al admin.

http://localhost:8000/admin

9 . 3

7.0.2 ADMIN

Administración de django con dos modelos registrados.

Figura 1: Administración de django, vemos los modelos registrados.

9 . 4

7.0.3 CREAR SUPERUSER

Actualmente no tenemos ningún usuario creado en elsistema. Podemos crear un usuario con todos los

permisos usando.Comando para crear un usuario superadministrador

python manage.py createsupersuser

9 . 5

7.0.4 BÁSICO

Django include los archivos o módulos (admin.py oadmin/__init__.py) llamados admin de todas las

aplicaciones registradas.

Registramos los modelos un una clase llamada admin.Ejemplo para que aparezca el modelo en el admin

from django.contrib import admin

from .models import Message

admin.site.register(Message)

9 . 6

7.0.5 PERSONALIZANDO MODEL ADMINEl admin es muy fácil y potente de personalizar.

from django.contrib import admin

from .models import Concept, Invoice

class ConceptInline(admin.TabularInline): model = Concept extra = 0

class InvoiceAdmin(admin.ModelAdmin): list_display = ["organization", "buyer", "date", "total"] inlines = [ConceptInline] search_fields = ["buyer", "organization"] list_filter = ["organization"] date_hierarchy = 'created_at'

admin.site.register(Invoice, InvoiceAdmin)

7.0.6 ADMIN CON INLINES

Figura 2: Pantalla de edición de admin.

9 . 7

Figura 2: Pantalla de edición de admin.

9 . 8

7.0.7 ADMIN LISTADO

Figura 3: Listado de usuarios y filtros para aplicar.

10 . 1

8 ESTÁTICOSNormalmente una aplicación web necesita más cosas,aparte del html generado por django para funcionar.

ImágenesJavascriptCssetc

La aplicación django.contrib.static�les, se encarga degestionar esto.

Archivos subidos por el usuario se llaman MEDIA

10 . 2

8.0.1 CONFIGURACIÓN BÁSICA

En settingsSTATIC_URL = '/static/'

En las plantillas{% load staticfiles %}<img src="{% static "my_app/myexample.jpg" %}" alt="My image"/>}"

10 . 3

8.0.2 DURANTE EL DESARROLLO.Hacemos que el servidor de django sirva los estáticos

from django.conf import settingsfrom django.conf.urls.static import static

urlpatterns = [ # ... the rest of your URLconf goes here ...] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

También podemos añadir para que sirva MEDIA

urlpatterns = [ # ... the rest of your URLconf goes here ...] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

10 . 4

8.0.3 EN PRODUCCIÓN

Es el servidor web, cdn, etc quien sirve los estáticos.

Para desplegar los archivos estáticos a dóndecorresponda se usa.

$ python manage.py collectstatic

11 . 1

9 FORMULARIOSNormalmente el manejo de formularios en web, es untrabajo tedioso y delicado.Hay que realizar la validación de los valores deentrada.Imprimir los erroresRenderizar las formularios parciales, con los informesde error y los valores.

Django viene con clases para trabajar con formularios.

11 . 2

9.0.1 FORMULARIOS

django.forms funciona de manera similar a los modelos.

Nuestra clase hereda de django.forms.Form yañadimos atributos como tipos de campo, cada uno deestos tipos corresponde con un campo de formulariohtml.

Formulario de django

from django import forms

class ContactForm(forms.Form): subject = forms.CharField() email = forms.EmailField(required=False) message = forms.CharField()

11 . 3

9.0.2 FORMULARIOS

Cada tipo de campo tiene asociado por defecto una clasewidget que será la encargada de renderizarlo.

De esta manera, los formularios pueden autogenerar elhtml de los campos.

Como se utiliza el formulario en las plantillas

<form action="/your-name/" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="Submit" /></form>

Podemos usar, para imprimir los formularios en pantallade diferentes formas

form.as_table, form.as_ul, form.as_p

11 . 4

9.0.3 FORMULARIOS

Los formularios reciben un diccionario (contexto).>>> data = {'subject': 'hello',... 'message': 'Hi there',... 'email': '[email protected]'}>>> f = ContactForm(data)>>> f.is_valid()True>>> f.is_bound == True>>> f2 = ContactForm()>>> f2.is_bound === False

Si la información está validada, podemos acceder a ellaen la propiedad cleaned_data

>>> f.cleaned_data{ 'message': 'Hi there', 'email': '[email protected]', 'subject': 'hello'}

11 . 5

9.0.4 VALIDACIÓN DE FORMULARIOS

Los campos que especificamos en la clase, ya se validanautomáticamente según las reglas que les especificamos.

Required, max_length, emailfield, max_value,min_value, etc..

11 . 6

9.0.5 VALIDACIÓN

Pero muchas veces queremos que el valor del campovalide además otra lógica.

from django import forms

class ContactForm(forms.Form): subject = forms.CharField() email = forms.EmailField(required=False) message = forms.CharField()

def clean_email(self): data = self.cleaned_data['email'] if "@example.com" not in data: raise forms.ValidationError("Ese dominio no existe, no me engañes!")

return data

11 . 7

9.0.6 MODELFORMS

Comúnmente, al trabajar con los modelos de la base dedatos vamos a tener que crear formularios para nuestros

modelos.

Django nos hace más fácil esa labor usando la clasedjango.forms.ModelForm

from django.forms import ModelFormfrom .models import Noticia

class NoticiaForm(ModelForm): class Meta: model = Noticia fields = ['fecha', 'titulo', 'texto']

noticia = Noticia.objects.get(pk=1)form = NoticiaForm(instance=noticia)

11 . 8

9.0.7 VALIDACIÓN DE MODELFORM

A la hora de validar un ModelForm, se realizan dos pasos

Validación del formularioValidación del modelo

11 . 9

9.0.8 MODELFORM

Si usamos .save() sobre un ModelForm válido, el modelose guardará en la base de datos y nos lo devolverá.

f = NoticiaForm(request.POST)

if f.is_valid(): noticia = f.save()

12 . 1

10 INTERNACIONALIZACIÓNY LOCALIZACIÓN

Hay soporte para

Traducción de textoFormateo de fecha y horaFormateo de númerosManejo de zonas horarias

12 . 2

10.0.1 INTERNACIONALIZACIÓN (I18N)

Lo que tiene que ver con la traducción de textosUSE_I18NLANGUAGE = lenguaje_pais -> es_ES

12 . 3

10.0.2 COMO SE USA

En pythonfrom django.utils.translation import ugettext as _from django.http import HttpResponse

def my_view(request): output = _("Welcome to my site.") return HttpResponse(output)

def my_view2(request, m, d): output = _('Today is %(month)s %(day)s.') % {'month': m, 'day': d} return HttpResponse(output)

12 . 4

10.0.3 PLURALES

from django.utils.translation import ungettextfrom django.http import HttpResponse

def hello_world(request, count): page = ungettext( 'there is %(count)d object', 'there are %(count)d objects', count) % { 'count': count, } return HttpResponse(page)

12 . 5

10.0.4 LAZY TRANSLATION

from django.db import modelsfrom django.utils.translation import ugettext_lazy as _

class MyThing(models.Model): name = models.CharField(_('name'), help_text=_('This is the help text'))

class Meta: verbose_name = _('my thing') verbose_name_plural = _('my things')

Solo se traducen cuando se usan. (Por ejemplo alrenderizar la plantilla)

12 . 6

10.0.5 EN PLANTILLAS

Ejemplo{% load i18n %}

<title>{% trans "This is the title." %}</title><title>{% trans myvar %}</title>

{% trans "starting point" as start %}{% trans "end point" as end %}{% trans "La Grande Boucle" as race %}

<h1> <a href="/" title="{% blocktrans %}Back to '{{ race }}' homepage {% endblocktrans %}">{{ race }}</a></h1><p>{% for stage in tour_stages %} {% cycle start end %}: {{ stage }}{% if forloop.counter|divisibleby:2 %}<br /> {% else %}, {% endif %}{% endfor %}</p>

12 . 7

10.0.6 OBTENIENDO EL IDIOMA Y CAMBIÁNDOLO

Ejemplo de como usar i18n en las plantillas{% load i18n %}

{% get_current_language as LANGUAGE_CODE %}<!-- Current language: {{ LANGUAGE_CODE }} --><p>{% trans "Welcome to our page" %}</p>

{% language 'en' %} {% get_current_language as LANGUAGE_CODE %} <!-- Current language: {{ LANGUAGE_CODE }} --> <p>{% trans "Welcome to our page" %}</p>{% endlanguage %}

12 . 8

10.0.7 EN JAVASCRIPT

En las urls se monta el javascript_catalogfrom django.views.i18n import javascript_catalog

urlpatterns = [ url(r'̂jsi18n/(?P<packages>\S+?)/$', javascript_catalog),]

En la plantilla<script type="text/javascript" src="{% url 'django.views.i18n.javascript_catalog' %}"></script>

12 . 9

10.0.8 EN JAVASCRIPT

Tendremos disponibles una serie de funcionesdocument.write(gettext('this is to be translated'));var object_count = 1 // or 0, or 2, or 3, ...

s = ngettext('literal for the singular case', 'literal for the plural case', object_count);

fmts = ngettext('There is %s object. Remaining: %s', 'There are %s objects. Remaining: %s', 11);s = interpolate(fmts, [11, 20]);

document.write(get_format('DATE_FORMAT'));

12 . 10

10.0.9 INTERNACIONALIZACIÓN DE URLS

from django.conf.urls import include, urlfrom django.conf.urls.i18n import i18n_patternsfrom django.utils.translation import ugettext_lazy as _

news_patterns = [ url(r'̂$', news_views.index, name='index'), url(_(r'̂category/(?P<slug>[\w-]+)/$'), news_views.category, name='category'), url(r'̂(?P<slug>[\w-]+)/$', news_views.details, name='detail'),]

urlpatterns += i18n_patterns( url(_(r'̂about/$'), about_views.main, name='about'), url(_(r'̂news/'), include(news_patterns, namespace='news')),)

12 . 11

10.0.10 URLS

i18n_patterns sólo está permitido un el archivo de urlsprincipal.

from django.core.urlresolvers import reversefrom django.utils.translation import activate

>>> activate('en')>>> reverse('news:category', kwargs={'slug': 'recent'})'/en/news/category/recent/'

>>> activate('nl')>>> reverse('news:category', kwargs={'slug': 'recent'})'/nl/nieuws/categorie/recent/'

12 . 12

10.0.11 CREACIÓN DE LOS FICHEROS DE TRADUCCIÓN

Una vez que en nuestra aplicación lo tenemos todopreparado para la traducción.Necesitamos extraer las cadenas traducibles para quese puedan traducir usando herramientas para ello.manage makemessages o django-adminmakemessages

12 . 13

10.0.12 MAKEMESSAGES

django-admin makemessages -l en

Creará locale/en/LC_MESSAGES/django.po, dentro de laaplicación que estamos traduciendo.

#: path/to/python/module.py:23msgid "Welcome to my site."msgstr """"

12 . 14

10.0.13 MAKEMESSAGES

Para volver a revisar de nuevo y extraer las cadenasnuevas usamos (para todos los idiomas)

django-admin makemessages -a

Para generar los ficheros de javascript se usa.django-admin makemessages -d djangojs -l en

12 . 15

10.0.14 COMPILANDO LOS MENSAJES

Cada vez que hagamos cambios en los archivos detraducción es necesario compilarlos a un formato más

eficiente que pueda leer django.django-admin compilemessages

Esto generará un fichero .mo por cada fichero .po queencuentre.

Para la compilación de los ficheros se usa gettext, en elmanual de django pone como instalarlo en windows.

https://docs.djangoproject.com/en/1.8/topics/i18n/translation/

12 . 16

10.0.15 LOCALEMIDDLEWARE

Si tenemos activo el localeMiddleware y no está puesta lacookie de idioma (no tenemos una sesión activa).

Django intentará adivinar las preferencias de idiomausando la cabecera Accept-language del navegador, y

nos redirigirá a la url del idioma adecuado.

12 . 17

10.0.16 IDIOMAS DISPONIBLES

En settings podemos encontrarLANGUAGES = ( ('de', _('German')), ('en', _('English')),)

LANGUAGE_CODE = 'es' # El idioma por defecto

12 . 18

10.0.17 LOCALIZACIÓN (L10N)

Lo que tiene tiene que ver con formateo y zonashorariasUSE_L10n

Podemos usarUSE_THOUSAND_SEPARATOR = True

Si queremos activar el separador de miles.

Para activar la localización en los modelos usamoslocalize

class CashRegisterForm(forms.Form): product = forms.CharField() revenue = forms.DecimalField(max_digits=4, decimal_places=2, localize=True)

12 . 19

10.0.18 EN LAS PLANTILLAS

Para usarlo en las plantillas usamos{% load l10n %}

{% localize on %} {{ value }}{% endlocalize %}

{% localize off %} {{ value }}{% endlocalize %}

{{ value|localize }}

12 . 20

10.0.19 LOCALIZACIÓN

Django tenía una aplicación localflavor para laslocalizaciones. Actualmente, ha sido extraída y vive como

aplicación de terceros en:

https://django-localflavor.readthedocs.org/en/latest/

Usando esta aplicación tendremos disponibles (enespaña por ejemplo)

ESCCCField. Campo que valida Banco EspañolESIdentityCardNumberField. Spanish NIF/NIE/CIFESPhoneNumberField,ESPostalCodeField,ESProvinceSelect,ESRegionSelectBICFormField, IBANFormField

13 . 1

11 LIBRERÍAS DE TERCERASPARTES

Librerías interesantes para trabajar con django.

django-pipeline (gestión de estáticos)easy-thumbnailsdjango-bracesdjangorestframeworkdjango-debug-toolbarcelery (procesos, colas de mensajes, async)weasyprint (generación de pdfs)requestsdjango-allauth (gestión de usuarios)

14 . 1

12 DEPLOY

14 . 2

12.0.1 STACK

uwsgiServidor de aplicaciones

nginxServidor web y sirve estáticos

supervisorManeja procesos, celery o uwsgi

redisServidor de cache

PostgreSQLServidor de base de datos

14 . 3

12.0.2 AUTOMATIZACIÓN

El deploy de una app de django es complejo, esimportante automatizar el proceso ya que normalmente

cuando haces deploy querrás hacer:

Descargar el nuevo código (git pull)Instalar los nuevos requirements de la app.Realizar migraciones de la base de datos.generación de estáticos.decirle al servidor de apps que recarge el código.

Ansible tiene módulos compatibles con django que tepermiten automatizar el proceso.