lunes, 12 de octubre de 2015

Desempolvando Django (4)

Hasta ahora hemos desarrollado algo muy básico: un listado de marcadores. Casi todo lo que hemos hecho ha sido definir y configurar cosas.

Veamos los siguientes pasos:

  • Cada marcador podía llevar asociada una imagen, mostrémosla en el listado

  • Debemos asociar una hoja de estilo a nuestras páginas

  • Debemos añadir alguna forma de crear nuevos marcadores y editar los existentes

  • Hay que preparar la aplicación para ser servida en un entorno "de producción", no desde el servidor de desarrollo

  • Y muchas más características y mejoras, por supuesto, pero vamos poco a poco


Mostrando la imagen en el listado


Recordemos cómo era nuestro modelo de datos (models.py):
from django.db import models

class Marcador(models.Model):
    titulo = models.CharField(max_length=200)
    url = models.CharField(max_length=500)
    descripcion = models.CharField(max_length=500)
    image = models.ImageField(upload_to='savebookmarks')

    def __str__(self):
        return self.titulo + ' (' + self.url + ')'

Al definir el atributo imagen especificamos la ruta donde se subirán las imágenes, es relativa al parámetro MEDIA_ROOT de settings.py

Si hemos creado unos cuantos objetos desde el "/admin", podremos mostrar su imagen en el listado. Para ello, en desarrollo, definiremos en settings.py una ruta más para ser servida como recurso estático. Esto "en producción" habrá que cambiarlo, pero por ahora seguimos con ello así:

En settings.py
STATIC_URL = '/static/'
MEDIA_ROOT = BASE_DIR + '/media'
STATICFILES_DIRS = (BASE_DIR + '/savebookmarks', MEDIA_ROOT)

STATIC se refiere a cómo se sirven recursos estáticos (hojas de estilo, JS, iconos, etc). MEDIA_ se refiere a cómo se sirven ficheros subidos por los usuarios. Por seguridad, en producción, separaremos totalmente ambos tipos de recursos. En desarrollo, los servimos igualmente con la app 'django.contrib.staticfiles' mediante la definición STATICFILES_DIRS.

En la template, incorporamos la imagen (marcador_list.html):
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static 'savebookmarks/estilo.css' %}" />

<h2>Marcadores</h2>
<ul>
    {% for m in object_list %}
        <li>
            <img src="{% static m.image %}" width="40" />
            <a target="_blank" href="{{m.url}}">{{ m.titulo }}</a>
            | (<a href="{% url "editMarcador" m.id %}">Editar</a>)
        </li>

    {% endfor %}
</ul>

<p><a href="{% url "addMarcador" %}">Añadir otro</a></p>

El tag {% static %} es atendido por la app 'django.contrib.staticfiles' y nos proporciona la URL relativa para ser servida por el servidor de desarrollo. En producción habrá que revisar esto. El resto de código lo revisaremos a continuación.

Enlazando una hoja de estilos


directorios

Como definimos en settings.py un
STATIC_URL = '/static/'

ahora podemos poner bajo esta URL nuestras hojas de estilo. El árbol de directorios del proyecto se va pareciendo a la figura.

La app 'django.contrib.staticfiles' encontrará los ficheros bajo static/ y los servirá adecuadamente.

Para enlazar estos ficheros, usamos el tag {% static %}, como se ha mostrado en la template.

En el paso a producción lo que se hace es utilizar un servidor web independiente para servir los recursos, en la documentación de Django se explica cómo hacerlo, por ahora mantenemos esta configuración en desarrollo.

Crear y editar marcadores


En este punto, utilizaremos el sistema de formularios de Django, que está muy bien pensado.

 

 

 

lunes, 5 de octubre de 2015

Desempolvando Django (3)

Lo siguiente que vamos a hacer es una vista para mostrar los marcadores ya guardados. Una de las tareas más típicas es sacar un listado de objetos guardados en la base de datos, para ello, Django tiene ya una vista preparada y lista para usar. Editemos nuestro savebookmarks/views.py
from django.views.generic import ListView
from savebookmarks.models import Marcador

class MarcadoresList(ListView):
    model = Marcador

Ya está, tenemos una vista que hereda de ListView en la que lo único que tenemos que hacer es decirle cuál es el modelo que se corresponde con los objetos que queremos listar.

En savebookmarks/urls.py, la invocamos con el método as_view() (que devuelve una respuesta adecuada como objeto HttpResponse)
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^$', views.MarcadoresList.as_view()),
]

Finalmente, necesitaremos una plantilla o template que muestre los objetos que está recuperando la ListView para nosotros.

Para que Django encuentre las plantillas, vamos a editar el settings.py dejando así la clave DIRS (en TEMPLATES):
'DIRS': os.path.join(SETTINGS_PATH, 'templates'),

(Se supone que con el ajuste  'APP_DIRS': True, Django ya es capaz de encontrar nuestras templates, pero parece que no funciona)

A continuación, escribimos la template en /savebookmarks/templates/savebookmarks/marcador_list.html:
<h2>Marcadores</h2>
<ul>
    {% for m in object_list %}
        <li><a target="_blank" href="{{m.url}}">{{ m.titulo }}</a></li>
    {% endfor %}
</ul>

La ListView nos proporciona una lista de objetos, object_list, sobre la que iteremos para mostrarlos.

marcadores

viernes, 2 de octubre de 2015

Desempolvando Django (2)

En la anterior entrada vimos cómo montar el entorno de desarrollo, ahora empezamos a esbozar el proyecto.

Se trata de una web básica que permite guardar marcadores, como el antiguo delicious.

Empezaremos con una sola pantalla que liste los marcadores guardados y ofrezca un campo (input) para guardar uno nuevo.

Recién creado el proyecto, la estructura de directorios es la siguiente:

  • <Raíz del proyecto>/

    • manage.py

    • marcadores/ (en este directorio editaremos los siguientes archivos):

      • urls.py

      • settings.py






Recordamos que el proyecto se creó con el comando
django-admin startproject marcadores

Ahora tenemos que crear una "app" dentro del proyecto
  python manage.py startapp savebookmarks

En esta app es donde escribiremos nuestro código. Por ahora seguiremos más o menos el tutorial de Django "Writing your first Django app".

Finalmente, en /marcadores/urls.py, mapearemos las dos URLs principales que utilizaremos, /admin y /savebookmarks
from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^savebookmarks/', include('savebookmarks.urls')),
    url(r'^admin/', include(admin.site.urls)),
]

Con esto, tras ajustar los parámetros necesarios en el settings.py y hacer un python manage.py migrate, podemos echar a andar el servidor de desarrollo.

(En versiones anteriores de Django no se disponía de migrations, si no recuerdo mal, había que hacerlo con una herramienta externa, South).

Empecemos a hacer algo útil en la app "savebookmarks"

Definamos el modelo (/savebookmarks/models.py)
from django.db import models

class Marcador(models.Model):
    titulo = models.CharField(max_length=200)
    url = models.CharField(max_length=500)
    descripcion = models.CharField(max_length=500)
    image = models.ImageField(upload_to='savebookmarks')

    def __str__(self):
        return self.titulo + ' (' + self.url + ')'

También crearemos un /savebookmarks/admin.py para poder actualizar desde la interfaz administrativa:
from django.contrib import admin
from .models import Marcador
admin.site.register(Marcador)

En este momento, como ha habido cambios en los modelos de datos, habrá que hacer el flujo de makemigrations/migrate como se describe en el tutorial.

En este punto, ya podemos empezar a crear desde la interfaz administrativa (http://127.0.0.1:8000/admin) algunos objetos del tipo marcador para no empezar con una base de datos vacía.

Lo siguiente, es crear la pantalla inicial. Lo más sencillo es recuperar el listado de marcadores ya creados, necesitamos definir una URL y una vista que la sirva. Definamos que la URL "/" sea atendida por la vista index, en /savebookmarks/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index, name='index'),
]

Recordemos que las URL "maestras" se definen a nivel proyecto (marcadores/urls.py) y aportan el prefijo, de tal forma que una URL con el patrón /savebookmarks será definida por savebookmarks/urls.py (fichero de definición de URLs de la app).

Sólo para comprobar que funciona, definimos una función index() en savebookmarks/views.py
from django.http import HttpResponse

def index(request):
    return HttpResponse("Aquí iría el listado de marcadores")

Y eso es todo por ahora. Lo siguiente es pensar cómo vamos a montar estas vistas, porque hay varias alternativas a la hora de escribir vistas:

  • Vistas como funciones (ejemplo anterior)

  • Class-based views (https://docs.djangoproject.com/en/1.8/topics/class-based-views/), que a su vez pueden ser

    • Genéricas

    • Escritas por nosotros