tutorial Posts

Creando un blog con django – parte 2

Llego el momento de crear los modelos, pero antes analicemos los datos que necesitamos guardar. Nuestro blog tendrá post, comentarios y tags, los que a su vez se componen de:

  • Post: fecha, titulo, contenido y etiquetas.
  • Etiqueta: nombre.
  • Comentario: autor, fecha, contenido.

Ahora bien, una etiqueta puede estar relacionada con varios post, así como un post tener varias etiqueta, por lo que tienen una relación many to many. Los comentarios por otro lado solo pertenecen a un post por lo que necesitan una clave foránea que lo relacione con el respectivo post.

Teniendo claro el modelo de la base de datos, es hora de escribir el código necesario para crear las tablas, afortunadamente django nos facilita la tarea. Editamos el archivo models.py ubicado en la carpeta de la aplicación:

# 1
from django.db import models

# 2
class Tag(models.Model):
# 3
tag = models.CharField(max_length=100, unique=True, db_index=True)
# 4
def __unicode__(self):
return self.tag

Veamos que hicimos:

  1. Importamos el modulo models.
  2. Creamos una subclase de models.Model, 
  3. Cada columna de la bd es representada por un atributo, en este caso tag es de tipo caracter (CharField), existen otros tipos de campo según el valor almacenar. Los argumentos describen las propiedades del campo como la cantidad de caracteres que puede contener (max_length), que no se permiten valores repetidos (unique), ademas de hacer que se indexe (db_index) ya que es comun hacer búsquedas como: buscar todos los post con tag django.
  4. el método __unicode__ permite dar un nombre mas significativo a las instancias, este es utilizarlo en el sitio administrativo.

Sabiendo esto es fácil crear las demás tablas:

# post
class Post(models.Model):
# la relación many to many entre Post y Tag
tags = models.ManyToManyField(Tag, blank=True)
title = models.CharField(max_length=200)
body = models.TextField()
# fecha de publicación, se agrega fecha automáticamente
pub_date = models.DateField(auto_now_add=True)

def __unicode__(self):
return self.title

class Comment(models.Model):
# Cada comentario pertenece a un post
post = models.ForeignKey(Post)
# nombre es opcional (blank) y por defecto es Anonimus (default)
name = models.CharField(max_length=100, blank=True, default="Anonimus")
# el cuerpo del comentario
body = models.TextField(verbose_name="comment")
# fecha de publicación, se agrega fecha automáticamente
date = models.DateField(auto_now_add=True)

def __unicode__(self):
return "Por " + self.name + " en " + self.post.title

La clave foránea y relación many to many se crea en una simple linea de código. Ahora sincronizamos nuevamente y entramos al interprete de python para introducir información en la base de datos:

$ python manage.py syncdb
$ python manage.py shell
# importamos los modelos
from blog.models import Tag, Post

# aun no hay tags así que creamos una
django = Tag(tag="django")
django.save()

# creamos un post
new_post = Post(title="mi primer post", body="El primer post que realizo")
new_post.save()
# agregamos un tag y volvemos a guardar
new_post.tags.add(django)
new_post.save()

Como vemos, para introducir un registro en la base de datos creamos una instancia de la clase adecuada y seguidamente llamamos el método save, ¿pero como recuperamos un registro? existen tres métodos para consultar la base de datos:

  • get: retorna un solo registro, lanza una excepción si la consulta retorna cero o mas de un registro.
  • filter: retorna un array con los registros que coinciden la consulta o un array vacío.
  • exclude: similar a filter pero retorna los registros que no cumplen con la consulta.
Estos métodos se acceden a través del atributo objects que poseen las subclases de models.Model.
# recuperar todos los post
Post.objects.filter()

# recuperar los primeros 10
Post.objects.filter()[:10]

Para refinar la búsqueda usamos argumentos que corresponden con los campos de la tabla:

# post segun titulo
Post.objects.filter(title="mi primer post")

Los campos que son claves foraneas (Post.tags, Comment.post) son algo especial: podemos seguir la relación escribiendo el nombre de la columna seguido de dos guiones bajos (_), pudiendo acceder el modelo al que apunta dicha relación. veamos un ejemplo:

# post con tag django
Post.objects.filter(tags__tag="django")

Al usar tags__ ya no estamos mas en Post sino en Tag, ahora podemos consultar los campos de esta tabla (tag). otro ejemplo:

# comentarios de posts con tag django
Comment.objects.filter(post__tags__tag="django")

Seguimos la relación a Post (post__) y consultamos la columna tags__ lo que nos lleva a Tag donde finalmente consultamos el atributo tag o_O.

Con esto tenemos lista la base de datos, en la próxima parte veremos como crear plantillas para visualizar estos datos.

Muchas gracias por su atención, no olviden dejar sus sugerencias, inquietudes y amenazas en los comentarios, hasta la próxima.

Creando un blog con django – parte 1

the killer framework

Primero quiero dejar claro que no soy un experto en django, así que si cometo algún error no duden en hacérmelo saber.

Este tutorial se divide en varias partes:

  1. instalación y configuración
  2. creación de modelos
  3. creación de vistas
  4. formularios
Instalación y configuración

Procedemos a descargar la ultima versión de django e instalarla como dice la pagina oficial:

$ wget http://www.djangoproject.com/download/1.3.1/tarball/
$ tar xzvf Django-1.3.1.tar.gz
$ cd Django-1.3.1
$ sudo python setup.py install

Ahora haciendo uso del script de administración creamos nuestro proyecto:

$ django-admin startproject tutorial

Esto crea el directorio tutorial, con los siguientes archivos:

  • manage.py: script para administrar el proyecto (sincronizar bd, crear aplicaciones, iniciar servidor…)
  • urls.py: las urls admitidas.
  • settings.py: configuración del proyecto (aplicaciones instaladas, directorios de plantillas, bd…)

Lo primero que haremos es crear nuestra aplicación (blog) usando el script manage.py

$ python manage.py startapp blog

Este comando crea el directorio blog con varios archivos en su interior, los cuales analizaremos en otra ocasión. Para terminar editamos el archivo settings.py e incluir la configuración de la base de datos y agregamos nuestra aplicación a la lista de aplicaciones instaladas:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'myblog',
# lo demás no es necesario para una bd sqlite
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
...
...
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog', # Nuestra aplicación
)

Sincronizamos la base de datos para crear las tablas necesarias:

$ python manage.py syncdb

Se pedirán algunos datos para crear la cuenta de administrador. Luego iniciamos el servidor de desarrollo con:

$ python manage.py runserver

Y listo, si entramos a la dirección localhost:8000 veremos una flamante pagina web confirmando que django esta correctamente configurado y listo para iniciar a desarrollar nuestra aplicación.

Eso fue todo por ahora, muchas gracias por su atención y no olviden estar pasando para la segunda parte.

Rehacer – Deshacer en javascript

En este tutorial intentaré explicar la forma de implementar la funcionalidad de deshacer y rehacer, una característica muy usada en los programas de escritorio y que muchas aplicaciones web no tienen (y hace mucha falta ya que errar es de humanos).
Descargar código
La idea consiste en tener objetos que representen las acciones (mover, eliminar, resaltar…), los cuales deben guardar el estado anterior del objeto afectado.

ChangeColorCommand = function(obj, color) {

this.obj = obj;
this.new_color = color;

// guardar estado anterior
this.prev_color = obj.style.backgroundColor;
}

ChangeColorCommand.prototype.execute = function() {
this.obj.style.backgroundColor = this.new_color;
}

ChangeColorCommand.prototype.undo = function() {
this.obj.style.backgroundColor = this.prev_color;
}

Cada objeto cuenta con dos métodos

  • execute: ejecuta la acción (dah)
  • undo: deshace la acción valiéndose de los datos guardados previamente en el constructor.

Las acciones son administradas por un objeto que mantiene dos pilas de acciones: las que se pueden deshacer y las que se pueden rehacer:

  • cuando ejecuta una acción, la guarda en undo_stack y borra toda acción que se podía rehacer
  • cuando se deshace algo, saca el ultimo objeto de la pila undo_stack, ejecuta el método undo y guarda la acción en la pila redo_stack.
CommandManager = function(max_undo) {

// máxima cantidad de acciones guardadas
max_undo = max_undo || 30;

// pilas de acciones
this.undo_stack = [];
this.redo_stack = [];

// ejecutar comando cmd
this.executeCommand = function(cmd){
cmd.execute();

// si se sobrepasa cantidad de acciones
// eliminar primer elemento
if (this.undo_stack.length >= max_undo) {
this.undo_stack.shift();
}
this.undo_stack.push(cmd);
this.redo_stack = [];
}

// deshacer acción
this.undoCommand = function() {
var cmd = this.undo_stack.pop();

// si existe acción
if ( cmd ) {
cmd.undo();
this.redo_stack.push(cmd);
}
}
}

Para realizar una acción creamos una instancia del objeto apropiado y la pasamos al CommandManager (previamente creado).

var UndoRedo = new CommandManager(),

box = document.getElementById("box");

// cambiar color a rojo
UndoRedo.executeCommand(new ChangeColorCommand(box, "red"));

// cambiar color a verde
UndoRedo.executeCommand(new ChangeColorCommand(box, "green"));

// cambiar de verde a rojo
UndoRedo.undoCommand();

// cambiar de rojo a blanco
UndoRedo.undoCommand();

Ahora solo resta crear mas acciones (mover, negrita, itálica…) dependiendo de la aplicación que estemos desarrollando.

Eso es todo, espero les haya servido; si tienen alguna duda o critica no duden en dejarla en los comentarios.