29 de noviembre de 2010

Generar diagrama de clases a partir de modelos Django

Una útil y sencilla aplicación web para generar diagramas uml, es yUML.

Siguiendo una sintaxis relativamente simple, podemos generar modelos y compartirlos cómodamente.

[Factura]<>1-*>[LineaFactura]

Generaría el siguiente modelo:


Ahora solo queda integrarlo en tu proyecto Django para generar los diagramas de clases a partir de tus modelos. Para ello utilizaremos un comando personalizado para manage.py y una implementación realizada por https://github.com/dzhibas

Nos descargamos el proyecto https://github.com/dzhibas/django-yuml/ y lo integramos en nuestra aplicación. Personalmente me gusta definir los comandos personalizados en una aplicación llamada commands. (Más info. sobre comandos personalizados abajo)

Por lo que tendremos una estructura similar a esta:


Ahora solo queda ejecutar el comando yuml.

Algunos ejemplos:
  • Generar sintaxis yuml para los modelos de una aplicación. (luego podemos copiar en la web y ver el diagrama)
$ ./manage.py yuml <aplicación>
  • Generar imagen o pdf con los modelos de una aplicación
$ ./manage.py yuml <aplicación> -o <file.pdf|file.png>
  • Generar imagen o pdf para todos los modelos de todas las aplicaciones
$ ./manage.py yuml -a -o <file.pdf|file.png>



Otra opción curiosa de yuml es si añadimos la opción --scruffy. Generaremos modelos con un estilo "más cool".


Referencias:
http://yuml.me/
https://github.com/dzhibas/django-yuml/
http://docs.djangoproject.com/en/dev/howto/custom-management-commands/

22 de noviembre de 2010

Cambiar puerto al servidor OC4J

Por defecto el servidor OC4J escucha en el puerto 8888.

Para cambiarlo editar <oc4j_root>/j2ee/home/config/default-web-site.xml y modificamos port, el atributo de la etiqueta base web-site:

<web-site
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/web-site-10_0.xsd" 
    port="8080"
    display-name="OC4J 10g (10.1.3) Default Web Site"
    schema-major-version="10"
    schema-minor-version="0" >

17 de noviembre de 2010

Distintas formas de inicializar un diccionario Python

A partir de un lista con tuplas llave/valor

>>> keys = ['a', 'b', 'c', 'd']
>>> values = [1, 2, 3, 4]
>>> mapping = zip(keys, values)
>>> mapping
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
>>> dict(mapping)
{'a': 1, 'c': 3, 'b': 2, 'd': 4}

A partir de un iterador

>>> def iter_dicc(num):
...     l = 'abcdefghijklmnopqrstuvwxyz'
...     for i in range(num):
...             yield (l[i], i+1)
>>> dict(iter_dicc(5))
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}

Directamente en el contrucctor

>>> dict(a=1, b=2, c=3, d=4)
{'a': 1, 'c': 3, 'b': 2, 'd': 4}

Referencias:
>>> help(dict)

15 de noviembre de 2010

Ejecutar una proceso bash para un conjunto de parámetros

Si queremos lanzar un proceso para un conjunto de parámetros de forma periódicos, podemos utilizar un bucle for y la orden seq en la siguiente instrucción:

for i in `seq -f "%02g" 1 10`; do ./script.sh 2010-11-$i; done

Esto ejecutará el script.sh para las fechas

./script.sh 2010-11-01
./script.sh 2010-11-02
...
./script.sh 2010-11-10

11 de noviembre de 2010

setting.py configurable por host y sistema operativo

Para un desarrollo de una aplicación Django donde intervengan varios colaboradores y en diferentes entornos de trabajo podemos trucar un poco el fichero setting.py.

Veamos como, poniendo un pequeño ejemplo.
  • Tenemos dos colaboradores b3ni y alex en el mismo proyecto.
  • Ambos colaboradores pueden desarrollar en diferentes entornos: linux/windows
  • Tenemos otro caso cuando el proyecto se ejecute en preproducción o producción.
Para que los desarrolladores puedan programar cómodamente y el proyecto pueda ser funcional en cualquier entorno, utilizaremos:

socket.gethostname()

Para identificar el host / usuario.

os.name

Para identificar la plataforma.

  • nt: Windows
  • posix: Linux

Ahora solo necesitamos encajarlo todo.

# diferentes tipos de configuraciones
import socket
import os

name_host = socket.gethostname()
name_os = os.name

if name_host == 'b3ni' or 'b3ni-laptop':
    # desarrollo en sobremesa y portatil
    # ----------------------------------
    DEBUG = True
    DIR_BASE = {'nt': r"C:/Users/b3ni/ws/project", 
                'posix': '/home/b3ni/ws/project'}[name_os]

    DATABASES = {
        'default': {
            'ENGINE':   'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
            'NAME':     DIR_BASE + r'/data.db', # Or path to database file if using sqlite3.
            'USER':     '', # Not used with sqlite3.
            'PASSWORD': '', # Not used with sqlite3.
            'HOST':     '', # Set to empty string for localhost. Not used with sqlite3.
            'PORT':     '', # Set to empty string for default. Not used with sqlite3.
        }
    }
    
    MEDIA_ROOT = DIR_BASE + r'/media'
    TEMPLATE_DIRS = (DIR_BASE + r"/templates/",)

elif name_host == 'alex':
    # desarrollo alex
    
    DEBUG = True
    DIR_BASE = {'nt': r"C:/Users/alex/workspace/dummy/project", 'posix': '/home/alex/workspace/dummy/project'}[name_os]

    DATABASES = {
        'default': {
            'ENGINE':   'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
            'NAME':     DIR_BASE + r'/data.db', # Or path to database file if using sqlite3.
            'USER':     '', # Not used with sqlite3.
            'PASSWORD': '', # Not used with sqlite3.
            'HOST':     '', # Set to empty string for localhost. Not used with sqlite3.
            'PORT':     '', # Set to empty string for default. Not used with sqlite3.
        }
    }
    
    MEDIA_ROOT = DIR_BASE + r'/media'
    TEMPLATE_DIRS = (DIR_BASE + r"/templates/",)
    
else:
    # PRODUCCION
    # ----------
    DEBUG = False

    DATABASE_ENGINE =   'mysql'
    DATABASE_NAME =     'xxx'
    DATABASE_USER =     'xxx'             # Not used with sqlite3.
    DATABASE_PASSWORD = 'xxx'             # Not used with sqlite3.
    DATABASE_HOST =     ''             # Set to empty string for localhost. Not used with sqlite3.
    DATABASE_PORT =     ''             # Set to empty string for default. Not used with sqlite3.

    EMAIL_HOST = 'xxx'
    EMAIL_HOST_PASSWORD = 'xxx'
    EMAIL_HOST_USER = 'xx'

    MEDIA_ROOT = '/server/project/media'
    TEMPLATE_DIRS = ('/server/project/templates/',)
    
# RESTO DE CONFIGURACION DJANGO .....