Mostrando las entradas con la etiqueta django. Mostrar todas las entradas
Mostrando las entradas con la etiqueta django. Mostrar todas las entradas

domingo, agosto 30, 2009

Primeros pasos con geodjango

Este es un minitutorial "expreso" para probar geodjango en debian testing con postgres 8.3, postgis y django 1.1

Pues lo primero es instalar los "juguetes":

$ apt-get install postgis postgresql-8.3 postgresql-plpython-8.3 
$ apt-get install python2.5 python-psycopg2 python-django ipython 
$ apt-get install gdal-bin python-gdal  
Ahora debemos configurar un poco postgres asi:
Debemos volvernos root y luego el usuario postgres

$ su 
$ su postrgres
$ psql template1

Este úlrimo comando nos conecta a postgres como el usuario postgres (el root del servidor de bases de datos), luego configuramos una plantilla para postigs (esto lo hacemos una sola vez)

template1=# ALTER USER postgres WITH PASSWORD 'postgres';
ALTER ROLE
Template1=#  \q

Luego:

$ cd /tmp
$ wget http://geodjango.org/docs/create_template_postgis-debian.sh
$ bash create_template_postgis-debian.sh
Esto nos crea la plantilla template_postgis, ahora volvemos a postgres:

$ createdb -T template_postgis geodjango

Salimos de postgres y del usuario root.
Ahora creamos un projecto y la app:
$ djano-admin startproject geodjango
$ cd geodjango
$ python manage.py startapp world

Luego editamos el settings de nuestro proyecto con el editor de nuestra preferencia (sugerencia rapida gedit)

$ gedit settings.py &
Dejamos las siguientes variables así

DATABASE_ENGINE = 'postgresql_psycopg2' 
DATABASE_NAME = 'geodjango'             # Or path to database file if using sqlite3.
DATABASE_USER = 'postgres'             # Not used with sqlite3.
DATABASE_PASSWORD = 'postgres'         # Not used with sqlite3.
DATABASE_HOST = 'localhost'
LANGUAGE_CODE = 'es'
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    'django.contrib.gis',
    'geodjango.world',
)

luego de guardar estos cambios:
$ mkdir world/data
$ cd world/data
$ wget http://thematicmapping.org/downloads/TM_WORLD_BORDERS-0.3.zip
$ unzip TM_WORLD_BORDERS-0.3.zip
$ cd ../..
 
Luego editamos otro archivo:
 
$ gedit world/models.py & 
 
from django.contrib.gis.db import models

class WorldBorders(models.Model):
    # Regular Django fields corresponding to the attributes in the
    # world borders shapefile.
    name = models.CharField(max_length=50)
    area = models.IntegerField()
    pop2005 = models.IntegerField('Population 2005')
    fips = models.CharField('FIPS Code', max_length=2)
    iso2 = models.CharField('2 Digit ISO', max_length=2)
    iso3 = models.CharField('3 Digit ISO', max_length=3)
    un = models.IntegerField('United Nations Code')
    region = models.IntegerField('Region Code')
    subregion = models.IntegerField('Sub-Region Code')
    lon = models.FloatField()
    lat = models.FloatField()

    # GeoDjango-specific: a geometry field (MultiPolygonField), and
    # overriding the default manager with a GeoManager instance.
    mpoly = models.MultiPolygonField()
    objects = models.GeoManager()

    # So the model is pluralized correctly in the admin.
    class Meta:
        verbose_name_plural = "World Borders"

    # Returns the string representation of the model.
    def __unicode__(self):
        return self.name
 
Luego vemos que todo vaya bien:
 
$ ./manage.py sqlall world 

Esto nos mostrara el sql de postgres para crear nuestro modelo:
 
BEGIN;
CREATE TABLE "world_worldborders" (
    "id" serial NOT NULL PRIMARY KEY,
    "name" varchar(50) NOT NULL,
    "area" integer NOT NULL,
    "pop2005" integer NOT NULL,
    "fips" varchar(2) NOT NULL,
    "iso2" varchar(2) NOT NULL,
    "iso3" varchar(3) NOT NULL,
    "un" integer NOT NULL,
    "region" integer NOT NULL,
    "subregion" integer NOT NULL,
    "lon" double precision NOT NULL,
    "lat" double precision NOT NULL
)
;
SELECT AddGeometryColumn('world_worldborders', 'mpoly', 4326, 'MULTIPOLYGON', 2);
ALTER TABLE "world_worldborders" ALTER "mpoly" SET NOT NULL;
CREATE INDEX "world_worldborders_mpoly_id" ON "world_worldborders" USING GIST ( "mpoly" GIST_GEOMETRY_OPS );
COMMIT;
 
 
Luego ejecutamos este sql:
$ ./manage.py syncdb
 
Lo que nos preguntara el usuario admin, su correo y la clave de acceso:
Creating table auth_permission
Creating table auth_group
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table django_admin_log
Creating table world_worldborders

You just installed Django's auth system, which means you don't have any superusers defined.
Would you like to create one now? (yes/no): yes
Username (Leave blank to use 'diegueus9'): <- Toma el usuario con el que estes haciendo esto
E-mail address:  <- Escribe tu correo
Password:
Password (again):
Superuser created successfully.
Installing custom SQL for world.WorldBorders model
Installing index for auth.Permission model
Installing index for auth.Message model
Installing index for admin.LogEntry model 

Luego creamos un scrip que cargará los datos de los archivos que descargamos:
$ gedit world/load.py
import os
from django.contrib.gis.utils import LayerMapping
from models import WorldBorders

world_mapping = {
    'fips' : 'FIPS',
    'iso2' : 'ISO2',
    'iso3' : 'ISO3',
    'un' : 'UN',
    'name' : 'NAME',
    'area' : 'AREA',
    'pop2005' : 'POP2005',
    'region' : 'REGION',
    'subregion' : 'SUBREGION',
    'lon' : 'LON',
    'lat' : 'LAT',
    'mpoly' : 'MULTIPOLYGON',
}

world_shp = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data/TM_WORLD_BORDERS-0.3.shp'))

def run(verbose=True):
    lm = LayerMapping(WorldBorders, world_shp, world_mapping,
                      transform=False, encoding='iso-8859-1')

    lm.save(strict=True, verbose=verbose)
 
Ahora lo que vamos a hacer es subir la info de las fronteras de los paises del mundo a nuestro modelo:
 
$ ./manage shell 
Python 2.5.4 (r254:67916, Feb 18 2009, 03:00:47)
Type "copyright", "credits" or "license" for more information.

IPython 0.9.1 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object'. ?object also works, ?? prints more.

In [1]: from world import load

In [2]: load.run()
...
...
...
Saved: Jersey
Saved: South Georgia South Sandwich Islands
Saved: Taiwan

In [3]: exit()
Do you really want to exit ([y]/n)? y
Ahora vamos a activar y usar nuestra interfaz automagica administrativa que nos da django:
$ gedit world/admin.py &
from django.contrib.gis import admin
from models import WorldBorders

class WorldBordersAdmin(admin.GeoModelAdmin):
    list_display = ['name', 'area', 'pop2005', 'lon', 'lat']
    search_fields = ['name']

admin.site.register(WorldBorders, WorldBordersAdmin)
 
Y luego editamos las urls:
$ gedit urls.py &
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/', include(admin.site.urls)),
)

Ahora ponemos a correr nuestro servidor de desarrollo:
$ ./manage runserver 9090
Validating models...
0 errors found

Django version 1.1, using settings 'geodjango.settings'
Development server is running at http://127.0.0.1:9090/
Quit the server with CONTROL-C.
Y en el navegador vamos a  http://127.0.0.1:9090/ veremos un error 404 como este:

Luego vamos a http://127.0.0.1:9090/admin y veremos esta interfaz:
alli ingresamos el usuario y la clave que configuramos cuando corrimos el comando syncdb y veremos esto:

Luego hacemos clic en World Borders y veremos algo así:

Allí podemos ordenar la lista por nombre  del pais (name), area (area), poblacion del 2005 (population 2005) o longitud y latitud del mismo. Ahora cerca al boton buscar ingresamos colombia y le damos buscar luego clic en colombia y veremos info y este mapa:

Y eso es todo, así tendremos nuestro "Hola mundo" con geodjango, django, postgres, postgis, etc...

viernes, marzo 20, 2009

Snippet de vista para i18n

Una de las cosas que nos ofrece django es vistas genéricas y soporte para localización (aka i10n) e internacionalización (aka i18n). Entonces una vez tenemos nuestro sitio con i18n o i10n pues lo que sigue es que le demos a nuestros usuarios la manera de escoger su idioma, django tiene un algoritmo par esto, sin embargo en algún punto nuestros usuarios querrán poder escoger su idioma preferido, para esto este framework nos da la opcion de una vista generica, sobre la cual encontrarán información en http://docs.djangoproject.com/en/dev/topics/i18n/#the-set-language-redirect-view.

Lo único es que esta vista espera que halla un formulario para que el usuario escoja su idioma y además que tengamos predefinida una página a la cual el usuario será redirigido después de seleccionar el idioma a lo cual le veo particularmente un inconveniente pues si el usuario ha llegado a un punto importante para él y es llevado a la página inicial pues no le agradará (en mi caso me molestaría), además si queremos tener la posibilidad de hacerlo desde una url y no una variable por post?

Para resolver este conflicto se modifica un poco la vista que nos trae django y la dejamos así:


def set_lang(request,lang):
    response = HttpResponseRedirect(request.META['HTTP_REFERER'])
    lang_code = u'%s' % lang
    if lang_code and check_for_language(lang_code):
        if hasattr(request, 'session'):
            request.session['django_language'] = lang_code
        else:
            response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
    return response

Esta vista espera que se escoja el idioma por una url y además redireccionará al usuario a la página en la que se encontraba, podemos hacerlo incluso en el urls.py y finalmente escogemos la url:

urlpatterns = patterns('',
    ... 
    (r'^set_lang/(?P\w{2})/$',set_lang),
    ...
)


de esta manera si se va a /set_lang/es/, django cargará todo nuestro sitio en español y volvera a la vista en la que lo hallamos hecho.

jueves, enero 22, 2009

Como usar el poderoso ORM de django en una aplicación de Escritorio

Alguna vez alguien me preguntaba que tan complejo seria usar el poderoso ORM de django en una aplicación de escritorio, lo cual me pareció una cuestión interesante pero debido al trabajo y la procrastinación™ lo dejé a algún lado, en estos días como ando melómano he estado dedicándole mucho tiempo a la musica, por cierto el reproductor que yo uso es Amarok, aunque también decidí probar el mpd, en fin cada cual tiene lo suyo y amarok me parece muy poderoso, probé otros mas como exaile, que intenta ser como amarok pero esta escrito en python con librerías gtk y este muy biche, entonces curioseando y por algunos errores de comportamiento en el amarok, me dio por revisar la estructura de la base de datos, y sinceramente no es lo mejor en modelos E-R, entonces quería ver que tan complejo sería hacer un nuevo reproductor de musica, principalmente que sea un frontend a los más comunes, amarok, banshee, mpd, y demás, incluso con una interfaz web al estilo ampache, pero pues obviamente en python y usando django, entonces empecé a realizar el esquema y de repente se me ocurrio la idea de tambien hacer un cliente de escritorio y volvio esta cuestión a mi.
Lo curioso del asunto es que es mucho más sencillo de lo que creia solo hay que poner tres lineas de código al inicio de nuestra aplicación:
Nota: es importante que crees el proyecto con el django-admin

import os, sys
os.environ['DJANGO_SETTINGS_MODULE']='proyecto.settings'
sys.path+=[os.path.split(os.path.split(os.path.abspath(__file__))[0])[0]]

La primera linea importa los modulos os y sys.
La seguna pone la variable de entorno DJANGO_SETTINGS_MODULE que django buscará para saber las configuraciones del archivo settings.py y la ultima agrega al path de python el path de donde se encuentra la carpeta del projecto.

Y de esta manera ya podemos usar todo lo que nos ofrece django en una aplicación de escritorio, el ORM, los validadores, incluso los forms.

viernes, diciembre 05, 2008

Cambiar permisos de archivos con python

Pues bien la historia comienza así:
Estoy desarrollando una aplicación con django para una galeria de arte, la url de la pagina en desarrollo es http://laotraferia.nodo-lab.com que después apuntará a http://www.laotraferia.com y pues probé con django-audioplayer que es un tag para embeber un reproductor de mp3 en la pagina, y no me funcionaba porque por algun motivo extraño al subir el mp3, me quedaba sin permisos de lectura en el servidor, por lo cual decidí que debia cambiarle los permisos cada vez que suban el archivo por lo cual debia reescribir el metodo save en el modelo:

def save(self,force_insert=False, force_update=False):
super(Audio,self).save(force_insert,force_update)


Y allí cambiar los permisos cada vez que guarden el objeto, por lo cual busque en la pagina de python, y encontre el metodo chmod en el modulo os, y primero intenté:

>>> import os
>>> os.chmod("archivo","777")

Al viejo estilo de linux, pero esto me genera un error pues el modo debe ser un entero y no una cadena, hice este cambio y no me genero error pero me cambió los permisos de una forma extraña, luego lei un poco más y es que esto debe hacerse usando otro modulo stat, de la siguiente manera:

>>> import os
>>> import stat
>>> os.chmod("archivo",stat.S_IRUSR+stat.S_IWUSR+stat.S_IRGRP+stat.S_IXGRP)

y de esta manera me deja los permisos de lectura y escritura para el usuario y lectura para los demás.

Estas variables del modulo stat son enteros, y equivalena a un 420.

Más adelante debo entender bien el porque de esto.

Actualización:
Definitivamente el problema siempre es capa 8, primero y más importante, a partir de la versión 1.0.2 django, existe una opcion de configuracion para establecer cuales son los permisos con los cuales nuestro framework favorito debe dejar los archivos que se suban a través del admin y formularios.
Esta variable es FILE_UPLOAD_PERMISSIONS y debe contener el valor que desamos tengan los archivos, si queremos no usar lo anterior del modulo stat, lo que debemos es anteponer un 0 al modo octal que conocemos de chmod, es decir en vez de poner un 420 que no nos es familiar podemos poner 0644 sin comillas ni nada, de esta manera python sabe que el 644 es un octal y no un entero. De hecho si entramos al interprete de python y escribimos 0644 este se nos mostrara como un entero (420)

martes, septiembre 02, 2008

E-commerce y django

Pues he estado revisando mi correo, particularmente la etiqueta de django-es, y alguna persona preguntaba por como hacer comercio electrónico con django, y le recomendaron la pagina http://www.satchmoproject.com/ esta el código con licencia bsd y algunos ejemplos de paginas donde la usan, e increíblemente (solo para mi) lo usan en la tienda de la Free Software Foundation en http://shop.fsf.org/, en mi incredulidad debia comprobarlo y lo primero que se me ocurrió fue ir a http://shop.fsf.org/admin y efectivamente  allí estaba, la interfaz administrativa de django.

martes, mayo 06, 2008

Extra

Después del fin de semana laaargo, en el cual me desconecte de la red y solo interactue en el "mundo real", llegué hoy a mi universidad y me di cuenta que la gente de google me envio un correo, solo para decirme que ya me habilitaron la cuenta de Google App Engine, ahora a hechar codigo!!!

martes, abril 29, 2008

Habemus Python!!!

Hace poco fue el dia D para python y django puesto que el gran hermano Google lanzó el beta de Google App Engine, un sdk de desarrollo de aplicaciones web powered by python, pues bien el ingeniero Camilo Nova, CEO de Axiacore, me pidió que lo asesorará sobre django, y lo hicé, en cuestion de 1 hora, le mostré el potencial de django y quedó sorprendido, por lo cual dijo que lo iba a pensar y hoy me dio la noticia de que AxiaStore se desarrollará en python, por lo cual puedo decir: Habemus Python!!!

miércoles, abril 23, 2008

Django sites

He estado revisando sitios "powered by django" en
http://www.djangosites.org y he encontrado http://dpaste.com/ que esta
como el mas alto por votos.

pdt: este post fue escrito probando la funcionalidad de blogger de mail2blog

quicknote

Hace poco me consegui un trabajo donde debo hacerle varios cambios a una aplicacion desarrollada en python con gtk como librera gráfica llamada quicknote, lo interesante del asunto es que corre en un celular nokia 810 que esta muy coqueto, ojala me pudiera comprar uno de estos, tienen un linux propio que es derivado de debian, por lo que tiene repositorios apt y todo eso, algunos paquetes como python ya estan portados a este dispositivo, y dentro de poco daran soporte para qt.

Es muy vacano ver como las empresas de dispositivos moviles como nokia, le apuestan a linux y sobretodo a python, otra cosa interesante que alcancé a ver que tiene soporte para pygame, por lo que se pueden desarrollar juegos para este movil.

Y tiene ssh!!! el mejor amigo del hombre geek!!! (frase de Santiago Ruano)