lunes, 29 de diciembre de 2008

Proxy CGI en Python

Usando OpenLayers, se me hizo necesario usar un script proxy para solicitar url's a través de AJAX que no están en el mismo dominio. En la documentación de OpenLayers ponen un ejemplo de un script en python para hacer el proxy, y está bien bueno para aplicaciones sencillas donde no se necesite mucha seguridad, acá está el link:

http://trac.openlayers.org/browser/trunk/openlayers/examples/proxy.cgi

jueves, 27 de noviembre de 2008

Cómo hacer una lista en orden inverso

Lo más fácil es ocupar reverse()

>>> a=range(5)
>>> a.reverse()
>>> a
[4, 3, 2, 1, 0]

Y si queremos ser un poco más rebuscados, podemos usar list comprehension

>>> a=range(5)
>>> a
[0, 1, 2, 3, 4]
>>> [a[i] for i in range(len(a)-1,-1,-1)]
[4, 3, 2, 1, 0]

martes, 18 de noviembre de 2008

Cómo inspeccionar objetos JavaScript

Estaba quebrandome la cabeza haciendo debugging de JavaScript, me puse a buscar cómo inspeccionar objetos y encontré esto:

http://www.codeproject.com/KB/miscctrl/JS_Inspect_Object.aspx

Es una función sencilla, que recorre el objeto recursivamente y devuelve un string con el objeto formateado a HTML.
Si usas firebug de firefox y pones la función en la consola, cuando la llamas inmediatamente abre la vista DOM, así que queda pulento como inspeccionador de objetos.

lunes, 20 de octubre de 2008

Encuentro Linux 2008, Universidad de Concepción

Este Año el tradicional Encuentro Linux se realizará en la Universidad de Concepción (que liiinda universidad :-) ) los días 23 y 24 de octubre, entre las conferencias habrá una de Django, que la dará Leo Soto, que presentó su trabajo Django on Jython, en la DjangoCon. Suerte Leo!

Página oficial del Encuentro: http://2008.encuentrolinux.cl/

lunes, 15 de septiembre de 2008

Número de linea para Excepciones

Para saber dónde se cayo nuestro programa cuando hay un tray except que abarca mucho código.

except Exception, error:
lineno = sys.exc_info()[2].tb_lineno
raise Excepction("Exception: %s at line " % (error,lineno))

Ojo que esto es sólo para el módulo actual, si la excepcion se arrastra desde otro módulo, hay que hacer lo mismo para el otro módulo.

miércoles, 3 de septiembre de 2008

DjangoCon... conferencia, se viene

Desde el 6 al 7 de septiembre en Montain View, California, USA. Se darán una serie de Conferencias Django, en el primer evento de este tipo organizado por la comunidad Django.
Incluso participa un chileno, Leonardo Soto, con una charla de Django on Jython. Muy bien!

Esperemos que los chicos de Django publiquen videos de las charlas y fotos del evento, para los que estamos más lejos.

La página oficial del evento es: http://djangocon.org

martes, 24 de junio de 2008

Malditas Fechas 2: Cómo pasar un string a datetime

En Python 2.5 basta con usar datetime.datetime.strptime, pero en Python 2.4 esa función no existe para datetime, por lo que hay que usar una combinación entre la librería time y datetime:

import datetime
import time
dt1=datetime.datetime(*time.strptime(date_in_string,'%Y-%m-%d %H:%M:%S')[0:6])


miércoles, 18 de junio de 2008

Pygments ... flores, azucar y muchos colores!


¿Algo más bonito y fácil de leer que el código convenientemente coloreado?. Bueno, eso mismo lo podemos hacer en Web y otras más...

Pygments es un resaltador de sintaxis de python (o python sintax highlighter), que nos permite embellecer el código de varios tipos de lenguaje u otro formato que definamos a gusto.
De hecho la página inicial tiene una sencilla interfaz para colocar código, definir en que formato quiero destacarlo y chan! chan! ejecutar el proceso de highlight!. El resultado es un HTML formateado con estilos CSS.

A ver si lo empiezo a usar para colorear el código que vaya poniendo aquí :-)

Gracias Masterfunk!

Cómo instalar Eggs

Puede que para muchos sea rematado de fácil, pero a mi me costó navegar por unas cuántas páginas para saberlo.... otra vez... ¿seré muy nerd?, bueno, justamente es re-fácil

$ sudo easy_install MODULE.egg

OJO, se necesita tener previamente instalado easy_install

miércoles, 11 de junio de 2008

¿Qué demora más al construir strings?

Siempre me he preguntado cuál es la forma más óptima de construir strings, ya que Python ofrece muchas maneras, bueno, para probar respecto al tiempo de generación hice unos pequeños scripts que iteran muuuchas veces sobre una construcción de string y el resultado fue el siguiente:

$ time python str_concatenate.py
real 0m10.959s
user 0m10.380s
sys 0m0.482s

$ time python str_onestring.py
real 0m15.336s
user 0m14.485s
sys 0m0.688s

$ time python str_join.py
real 0m12.853s
user 0m12.075s
sys 0m0.613s


Conclusión:
El uso de " "+str(algo1)+" "+str(algo2) es más rápido,
le sigue el uso de join (si es una lista de cosas) " ".join(str(algo1),str(algo2))
y por último "%s %s" % (algo1,algo2), que yo pensé que era el más rápido :-(

Como decía mi primo: "plop! Pepo"

viernes, 6 de junio de 2008

List Comprehension

(Material de un Taller que hicimos en la pega)

List Comprehension
==================
List comprehensions provide a concise way to create lists without resorting to use of map(), filter() and/or lambda. The resulting list definition tends often to be clearer than lists built using those constructs. Each list comprehension consists of an expression followed by a for clause, then zero or more for or if clauses. The result will be a list resulting from evaluating the expression in the context of the for and if clauses which follow it. If the expression would evaluate to a tuple, it must be parenthesized.

Simples
=======
>>> [x for x in [1,3,5,7,9]]
[1, 3, 5, 7, 9]

>>> [x for x in range(5)]
[0, 1, 2, 3, 4]

>>> [x for x in range(2,10,2)]
[2, 4, 6, 8]

También se pueden anidar varios ciclos for (Gracias Dorian!)

>>> [ (x,y) for x in [1,2,3] for y in [4,5,6]]
[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

Strings funcionan como listas
=============================
>>> [x for x in "Hola compadre"]
['H', 'o', 'l', 'a', ' ', 'c', 'o', 'm', 'p', 'a', 'd', 'r', 'e']



Cálculos:
=========
>>> [x*x for x in range(5)]
[0, 1, 4, 9, 16]


Condiciones:
============
>>> [x*x for x in range(5) if x%2]
[1, 9]
>>> [x*x for x in range(6) if x>3]
[16, 25]


Parseo de archivos:
===================
>>> stream="""Nombre, calorias, cantidad
... perejil, 10, 5
... betarraga, 20, 2
... zanahoria, 30, 10
... chocolate, 1000, 1"""
>>> [line.split(',') for line in stream.split('\n')[1:]]
[['perejil', ' 10', ' 5'], ['betarraga', ' 20', ' 2'], ['zanahoria', ' 30', ' 10'], ['chocolate', ' 1000', ' 1']]

>>> [[e.strip() for e in line.split(',')] for line in stream.split('\n')[1:]]
[['perejil', '10', '5'], ['betarraga', '20', '2'], ['zanahoria', '30', '10'], ['chocolate', '1000', '1']]

>>> [ "Nombre: %s, calorias: %s, cantidad: %s" % tuple([e.strip() for e in line.split(',')]) for line in stream.split('\n')[1:]]
['Nombre: perejil, calorias: 10, cantidad: 5', 'Nombre: betarraga, calorias: 20, cantidad: 2', 'Nombre: zanahoria, calorias: 30, cantidad: 10', 'Nombre: chocolate, calorias: 1000, cantidad: 1']


Capturar solo los números
=========================
>>> values = [[e.strip() for e in line.split(',')] for line in stream.split('\n')[1:]]
>> [ [int(v) for v in line if v.isdigit()] for line in values]
[[10, 5], [20, 2], [30, 10], [1000, 1]]


Pasar los valores formateados
=============================
>>> values_formated = [ ( l[0],int(l[1]),int(l[2]) ) for l in values]
>>> [line for line in values_formated if line[2]>2]
[('perejil', 10, 5), ('zanahoria', 30, 10)]


Suma condicionada: Sumar calorias de todos los elementos con cantidad>2
============================================
>>> sum( [line[1] for line in values_formated if line[2]>2] )
40


Construir strings usando List comprehension
===========================================
Ejemplo para armar una SQL que haga union de varias tablas
>>> " UNION ".join(
... ['SELECT max(%s) as time FROM "%s".%s' % tuple(x[:1]+['SCHEMA_NAME']+x[1:])
... for x in [
... ['field1','table1'],
... ['field2','table2'],
... ['field3','table3'],
... ['field4','table4']
... ]
... ]
... )
'SELECT max(field1) as time FROM "SCHEMA_NAME".table1 UNION SELECT max(field2) as time FROM "SCHEMA_NAME".table2 UNION SELECT max(field3) as time FROM "SCHEMA_NAME".table3 UNION SELECT max(field4) as time FROM "SCHEMA_NAME".table4'



Creación de Dictionary
======================
Ejemplo:
========
Esto no es necesario hacerlo:
d={}
for row in rows:
if d.has_key(row[0]):
d[row[0]].append((row[1], row[2]))
else:
d[row[0]] = [(row[1], row[2])]

Basta con hacer:

>>> rows=[[1,2,3,4,5],[6,7,8,9,0],[11,12,13,14,15]]
>>> d={}
>>> d.update( [ (r[0],(r[1],r[2])) for r in rows] )
>>> d
{1: (2, 3), 11: (12, 13), 6: (7, 8)}



Interseccion, Union, Diferencia entre listas
============================================
>>> A=[1,2,3,4,5]
>>> B=[2,4,6,8]
# Intersecion
>>> [x for x in A if x in B]
[2, 4]
>>> [x for x in B if x in A]
[2, 4]
# Difference
>>> [x for x in B if x not in A]
[6, 8]
>>> [x for x in A if x not in B]
[1, 3, 5]
>>>

Otra forma usando Set
=====================
>>> set(A).intersection(B)
set([2, 4])
>>> list(set(A).intersection(B))
[2, 4]
>>> list(set(B).intersection(A))
[2, 4]
>>> list(set(B).difference(A))
[8, 6]
>>> list(set(A).difference(B))
[1, 3, 5]


Set:
====
A set object is an unordered collection of distinct hashable objects. Common uses include membership testing, removing duplicates from a sequence, and computing mathematical operations such as intersection, union, difference, and symmetric difference. New in version 2.4.


Desafío:
=========

¿Se puede hacer esto con list comprehension?
¿si? ¿no? ¿porqué? ¿cómo?
>>> l=[]
>>> for n in ['Francisco','Richard', 'Luis']:
... for c in ['Fruta','Carne','Verdura']:
... if not(n=='Luis' and c=='Carne'):
... l.append('%s come %s' % (n,c))
...
>>> l
['Francisco come Fruta', 'Francisco come Carne', 'Francisco come Verdura', 'Richard come Fruta', 'Richard come Carne', 'Richard come Verdura', 'Luis come Fruta', 'Luis come Verdura']

lunes, 2 de junio de 2008

Luego de Webprendededor Concepción 2008

Bien motivado me quedé luego de escuchar a todos estos "geaks" (como uno) hablando de emprendimiento, innovación, creatividad, etc...

Noticia en Diario El Sur

Concepción no es un Santiago chico
Webprendedor, con las pilas puestas en Concepción

viernes, 30 de mayo de 2008

lunes, 26 de mayo de 2008

Webprendededor Concepción 2008



Se ven algunas charlas interesantes: Los chicos de Needish, Metrik y el Francotirador, entre otros.

A apoyar este tipo de iniciativas!
En Concepción el día sábado 31 de Mayo

Más encima en el mismo lugar donde estudié...
De allá somos...

import datetime vs from datetime import datetime

Para todos los que desarrollan en Python:

Si van a usar la libraría datetime

Es preferible hacer esto:
import datetime
dtnew = datetime.datetime(2008,5,20)


Que esto:
from datetime import datetime
dtnew = datetime(2008,5,20)


Pues usando el segundo caso, si hacen import de otro modulo que esté
usando datetime, el intérprete se puede marear con los nombres y
pueden haber errores como:
Module object is not callable
TypeError: descriptor 'time' requires a 'datetime.datetime' object but
received a 'int'



Por último si les da demasiada lata escribir datetime muchas veces
pueden hacer algo como esto:
from datetime import datetime as dtime
dtnew = dtime(2008,5,20)

Así no se vuelve a usar el nombre datetime como función y objeto(not
callable) a la vez.

miércoles, 21 de mayo de 2008

Búsquedas por date y datetime

Haciendo un filtro por fechas me di cuenta que no era lo mismo hacer

date1 = datetime.datetime.now().date() (date1 es tipo date)
xxxx.objects.filter(date__lte=date1)

que

date2 = datetime.datetime.now() (date2 es tipo datetime)
xxxx.objects.filter(date__lte=date2)

Obvio, uno de ellos considera horas, minutos y segundos

Así que ojo si hay que decidir un intervalo de días para datos tipo datetime, hay que considerar el día completo:
'2008-05-21 23:59:59'

O sea:
date2= datetime.combine(date1, time(23,59,59))

miércoles, 7 de mayo de 2008

Cómo truncar palabras my largas en la template

{{ object.comments|truncatewords:15|make_list|slice:":80"|join:"" }}
{% if object.comments|truncatewords:15|make_list|slice:":80"|length_is:"80" %} ...{% endif %}

Lo que hice fue pasar el string a una lista, cortarlo, y luego hacer un join para volver a convertirlo string, para dejarlo más bonito: un if que si coincide en largo con el string cortado le agrega los puntos suspensivos ...

La otra opción era armarse una función para el sistema de templates, como aquí:
http://www.djangosnippets.org/snippets/163/

Pero a mí, hacer eso me dió lata :-)

lunes, 14 de abril de 2008

Cómo usar links en herramienta Admin de Django

Es muy fácil y yo me quebré la cabeza un buen rato cambiando las plantillas y revisando el código de Django.
Si uno necesita poner links en en la herramienta Administración de Django, no funciona así no más pues si uno hace algo como esto:
  def get_link(self):
link = self.sample_url
if link:
return '<a href="http://www.serversample.cl/">click here</a>'
return ''
class Admin:
list_display = (...,'get_model_link')

Django Admin escapa los textos, así que el resultado en el browser es esto:

<a href="http://www.serversample.cl/">click here</a>

Para que Django Admin no escape los textos hay que hacer lo siguiente:
  def get_link(self):
link = self.sample_url
if link:
return '<a href="http://www.serversample.cl/">click here</a>'
return ''
get_link.allow_tags = True

Y agregar el campo al list_display en la clase Admin:
  class Admin:
list_display = (...,'get_model_link')

Con esto no sólo se pueden crear links, sino que se puede agregar cualquier tag que se necesite (scripts, color de texto, formato texto, divs ... etc...)

miércoles, 9 de abril de 2008

Redirect desde Apache

Yo no lo sabía... ¿seré muy nerd?

Ocurre que se puede hacer un redirect directamente desde apache sin necesidad de pasar por alguna página que tenga un header o algún invento similar.
Lo que hay que hacer es editar el archivo de confiuguración de apache (en la instalación por defecto en Linux está en /etc/http/conf/httpd.conf) y agregar la siguiente línea:

Redirect /index.html http://ww.sampleserver.com/application

Y no hagas esto:
Redirect /index.html http://ww.sampleserver.com/application
Porque termina en un loop infinito, que intenta cargar una pagina algo así como: http://ww.sampleserver.com/application/application/application/application/application/application/application/application ......

viernes, 28 de marzo de 2008

Error 404 y 505 diferentes para cada aplicación dentro de un mismo proyecto Django

Django por defecto usa una template error 404 y error 500 por proyecto.
Pero... ¿qué pasa si uno quiere usar diferentes páginas de error 404 y 500 para distintas aplicaciones dentro de un mismo proyecto?
Después de estar tratando de crear mi propio handler 404, y darme cuenta que no podía usar uno distinto por aplicación (Los handler 404 y 500 siguen siendo los mismos para el proyecto), me di cuenta que podía usar dos settings.py y usar las directivas de configuración de apache para usar uno u otro, dependiendo de la URL a la que se acceda.
Entonces, en el httpd.conf (o en alguna extensión que se coloque en el dir httpd/conf.d/):

SetHandler python-program
PythonHandler django.core.handlers.modpython
PythonPath "['/home/userx/djangoapps'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE proyect.settings
PythonDebug On


SetHandler python-program
PythonHandler django.core.handlers.modpython
PythonPath "['/home/userx/djangoapps'] + sys.path"
SetEnv DJANGO_SETTINGS_MODULE proyect.settings_app2
PythonDebug On

Luego tengo dos settings, en el nuevo (app2) dejo mi aplicación antes que las demás para que ubique las templates 404 y 500 desde ahí.

INSTALLED_APPS = (
...
'proyect.app2',
'proyect.app1',
...,
)


y pongo debug=False y chan, chan! tengo un sólo proyecto con dos aplicaciones que direccionan a distintas páginas de error 404 y 500.
Muy chanchullesco? Bueno... por lo menos resulta.

lunes, 24 de marzo de 2008

Malditas fechas!

Siempre me ha complicado el manejo de fechas en cualquier lenguaje, aquí algunos tips de fechas en python:

>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2008, 3, 24, 14, 3, 2, 704594)
>>> "%s" % datetime.datetime.now()
'2008-03-24 14:03:15.171016'

Lo mismo pero sin decimales
>>> "%s" % datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
'2008-03-24 14:05:19'

Y acerca de diferencia entre fechas
>>> d1=datetime.datetime.now()
>>> d2=datetime.datetime.now()
>>> ddiff=d2-d1
>>> ddiff
datetime.timedelta(0, 15, 565414)
>>> str(ddiff)
'0:16:12.826069'

Lo mismo pero sin decimales
>>> str(ddiff)[:len(dstr)-7]
'0:16:12'

Ya lo sé, ya lo sé, no es muy bonito, la otra opción más correcta sería:
>>> h=ddiff.seconds/3600
>>> m=ddiff.seconds/60-h*60
>>> s=ddiff.seconds-h*60-m*60
>>> "%i:%i:%i" % (h,m,s)
'0:16:12'


Obviamente, siempre se puede ver la documentación oficial:
http://docs.python.org/lib/module-datetime.html

martes, 18 de marzo de 2008

Cómo obtener dirección IP en Django

Fácil, usar el objeto request: request.META['REMOTE_ADDR']

Después de cabecearme un rato, vi que la documentación lo decía:
http://www.djangoproject.com/documentation/request_response/#attributes

Hice una prueba para ver cómo se veía request.META y esto fue lo que obtuve:
[AUTH_TYPE]: None
[HTTP_COOKIE]: sessionid=4993370cb1d7b51eb013a6f12eccacc4; __utma=258392522.165289698.1205853464.1205853464.1205853464.1; __utmz=258392522.1205853464.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); __utmb=258392522.1; __utmc=258392522.1
[SERVER_SOFTWARE]: mod_python
[SCRIPT_NAME]: None
[REQUEST_METHOD]: GET
[PATH_INFO]: /test/
[SERVER_PROTOCOL]: HTTP/1.1
[QUERY_STRING]: None
[HTTP_TE]: deflate, gzip, chunked, identity, trailers
[CONTENT_LENGTH]: 0
[HTTP_ACCEPT_CHARSET]: iso-8859-1, utf-8, utf-16, *;q=0.1
[REMOTE_USER]: None
[HTTP_CONNECTION]: Keep-Alive, TE
[SERVER_NAME]: kultrun.intra.wiseocean.cl
[REMOTE_ADDR]: 192.168.10.68
[PATH_TRANSLATED]: None
[SERVER_PORT]: 0
[HTTP_USER_AGENT]: Opera/9.26 (X11; Linux i686; U; en)
[HTTP_HOST]: 192.168.10.68
[HTTP_COOKIE2]: $Version=1
[HTTP_CACHE_CONTROL]: no-cache
[HTTP_ACCEPT]: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1
[GATEWAY_INTERFACE]: CGI/1.1
[HTTP_ACCEPT_LANGUAGE]: en-US,en;q=0.9
[REMOTE_IDENT]: None
[CONTENT_TYPE]: None
[REMOTE_HOST]: None
[HTTP_ACCEPT_ENCODING]: deflate, gzip, x-gzip, identity, *;q=0


En caso de necesitar la IP directamente desde python sin pasar por django, se puede hacer:

import socket
socket.gethostbyname(socket.gethostname())
socket.gethostbyname_ex(socket.gethostname())

lunes, 17 de marzo de 2008

Buenos Links para tener a mano

Django
Página Oficial: http://www.djangoproject.com/
Documentación oficial: http://www.djangoproject.com/documentation/
Django Book: http://www.djangobook.com/
Comunidad de usuarios Django en el mundo: http://djangopeople.net/
Django Snippets: http://www.djangosnippets.org/
B-List, aquí siempre hay varios artículos Django: http://www.b-list.org/
Blog de Marcelo Ramos, en el blog de este loco he visto cosas interesantes.
Igor Weblog, otro blog con cosas Django

Python
Página oficial: http://www.python.org/
Una muy buena referencia rápida: Python 2.4 Quick Reference
Manejo fechas en Python: http://pleac.sourceforge.net/pleac_python/datesandtimes.html

 

jueves, 13 de marzo de 2008

¿Sabías que en python bool('False')=True ?

Bueno, yo no lo sabía y me costó un rato encontrar un error asociado a eso.
En realidad es un asunto lógico un string vacío es False y uno lleno True.

Interesante el juego de palabras, ¿no?

viernes, 7 de marzo de 2008

Cómo crear un Blog en Django 0.96 y no morir en el intento


Después de una ardua tarea buscando y probando Blogs tipos add-on para Django 0.96, me pareció pertinente compartir, a ver si a alguien le sirve, y si a nadie le sirve, por último para no olvidarme de lo que hice...

Primero Googleando, encontré y probé estos blogs:
http://code.google.com/p/django-diario/
http://code.google.com/p/django-basic-blog/
http://code.google.com/p/coltrane-blog/

Eran para la versión de desarrollo de Django, e inicialmente yo creía inocentemente que iba a poder hacer los suficientes hacks para que anduvieran en Django 0.96 y que no iban a ser muchos.... mala idea.... después de un par de días, me di por vencido... hay muchas cosas en las urls y en varias otras librerías que se han mejorado.

Después, encontré una buena información en este sitio:
http://paltman.com/2008/02/02/i-want-to-move-my-blog-to-django/

Finalmente instalé y empecé a probar este:
http://code.google.com/p/blogmaker/
Que fue el único (de la lista anterior y otras) que encontré para Django 0.96. Pero tuve el problema que es para Python 2.5 ... y yo tengo Python 2.4!!!!!!!
Inconveniente: Me era muy costozo cambiar de 2.4 a 2.5 (además mi jefe dijo: que sea la última opción... ni modo)
Solución: Vi que de Python 2.5 sólo se usaba la librería hashlib, y más específicamente md5, entonces reemplacé hashlib.md5 por md5.md5().hexdigest()

Otra cosa fue que por defecto Django 0.96 trae los siguientes TEMPLATE_CONTEXT_PROCESSORS
("django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n")
Y BlogMaker usa además otro:
django.core.context_processors.i18n
Para agregarlo, hay que modificar el settings.py del proyecto y agregarle esto:
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.request",
)


Después me faltaba una librería: Python-Markdown
La bajé de aquí: http://www.freewisdom.org/projects/python-markdown/
E instalarla fue muy fácil:
$ unzip python_markdown-1.7.rc1.zip
$ cd python_markdown-1.7

$ sudo python setup.py install

Después tuve que cambiar la url (que está hardcoded) a la que salta la plantilla para dejar comentarios:
$ vi blogmaker/comments/templates/comments/comment_form.html

Eso fue todo y la cosa empezó a andar picho caluga.... ahora que mi amigo que está editando las plantillas para darle nuestro formato me esté diciéndo que están medio juleras, es otra cosa.... vamos a ver cómo evoluciona nuestra experiencia con BlogMaker para Django.

Bueno, y si alguien sabe cómo hacer esto que hice de una manera más fácil... SUELTA LA PEPA!!! y di como se hace! ... por lo menos una persona (yo), estará muy agradecido ;-

Django & Python Tips

Un lugar para reunir información, tips, noticias, paltas acerca de Django (El Web framework para perfeccionistas) y Python (El lenguaje interactivo, expresivo y legible, que a muchos nos ha hecho fanáticos de él).

Estoy haciendo esto como medio para guardar las típicas paltas que sino se escriben después cuesta acordarse, los links que se ven bacanes y que después dije "DONDE #$@&! LO ANOTÉ!!!", las noticias que no quiero olvidar y en fin, todo lo compartible que vea por ahí del mundo Django y Python.

... Y en español (por ahora)