Enmig d'aquest silenci
Escrit per Aaloy a 25 de April , 2009 a les 11:49 a.m.
El amics de No diguis dois han tret nou disc, el segon ja, anomenat Enmig d'aquest silenci.
Mentre posam la web definitiva per ara el domini apunta al Facebook, en poder he de recuperar el projecte i penjar les lletres i demés.
Encara no els he pogut convèncer de que publiquin en Creative Commons, però no perd l'esperança, potser el proper disc?
Des d'aquí donar-los l'enhorabona pel disc i per l'empenta que tenen. Esper que faceu molts bolos aquest estiu! :)
Traducciones/Translations by apertium
1 comentari, 0 trackbacks (URL) , Tags: General
Visor de logs amb Django
Escrit per Aaloy a 22 de April , 2009 a les 8:53 p.m.
L'altra dia em vaig trobar amb la necessitat de mostrar els logs de l'aplicació a la plana web que estava desenvolupant.
Per anar bé, els logs han de ser dinàmics, és a dir, la plana ha de refrescar-se segons apareguin noves línies de log (i això vol dir Ajax). La idea és tenir quelcom com el tail -n 100 f ... del Linux. Per la naturalesa de les peticions Http, no podem arribar a tenir la funcionalitat del tail, però podem atracar-nos-hi un poc. Aquest article explica com ho podem fer utilitzant Django, Python i jQuery.
El javascript
La part del navegador ha de refrescar-se automàticament i sols el tros que correspongui a la visualització dels logs. A cada refresc haurà de cridar al servidor, obtenir la informació del log i presentar-la.
Per aconseguir això utilitzarem Jquery i un afegitó anomenat Timers. Aquest plugin ens permet definir de manera una funció que s'executarà cada x milisegons fins que l'aturem o tanquem el navegador.
El temps de refresc dependrà de la nostra aplicació, i el truc està en donar-li un temps un poc menor que la velocitat a la que la nostra aplicació genera les línies de log. No fa falta mirar-s'hi gaire, sols és per donar una major sensació d'actualització en temps real i que es mostri la informació línia a línia. Si li donam un temps major farem menys peticions i la presentació del log potser es faci per blocs de línies.
També necessitarem fer una cridada Ajax al servidor per a que ens doni les línies de log. Això ho podem fer directament amb jQuery, amb la funció jQuery.ajax per exemple. Veurem que a més del text del log necessitam la darrera posició llegida, així que farem servir el getJSon, que ens permetrà obtenir la informació de manera més estructurada.
El servidor
Per simular el tail farem un poc de trampa. La primera vegada que es faci la petició ens situarem al final del fitxer de log i la segona ja enviarem la informació. És a dir, mostram al informació a partir de la segona vegada que es crida la funció. Com que el temps es suposa que és petit no té massa importància i simplifica molt la programació. Hem de tenir en compte que l'obtenció de log ha de ser ràpida.
Per a posicionar-nos farem servir la funció seek i tell ens donarà la posició resultant una vegada llegit el fitxer. Aquesta posició és la que anirem passant a cada petició, de manera que quan tornem a llegir el log, ho farem a partir de la darrera posició llegida. A l'exemple a més he fet servir la funció reverse per tal d'ordenar la llista de línies llegides de més nova a més antiga i simular l'scroll.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | from django.http import HttpResponse from django.utils import simplejson def _tail(f, actual = 0): """ Returns a tuple with the actual position on the file and the last read lines in html format. """ text ="" if actual == 0: f.seek(0, 2) else: f.seek(actual) log = f.readlines() if log: log.reverse() text = "<br/>".join(log) return f.tell(), text def tail(request): "Tail simulation" f = open('sample.log', 'rU') pos = int(request.GET['pos']) pos, msg = _tail(f, actual= pos ) f.close() data = {'msg': msg, 'pos' : pos } return HttpResponse(simplejson.dumps(data)) |
Fixem-nos que el que tornam és una estructura json, creada a partir d'un diccionar Python mitjançant el simplejson.
A més consumim la posició del fitxer des de la que hem de començar a llegir, que vindrà donada pel paràmetre get. No he posat validacions ni tractament d'excepcions, ho deix com a exercici per al lector (això sempre queda bé dir-ho quan un no té massa ganes de fer feina :-P )
Amb el que ara veim del codi de servidor, el codi javascript ja és entenidor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <script type="text/javascript"> $(function() { var pos = 0; var demos = $("div.wrapper div.demos"); var active = false; $('#log').ajaxStart(function(){$('#loading').show()}); $('#log').ajaxStop(function(){$('#loading').hide()}); $('.controlled-interval', demos). find('.start').css("cursor", "pointer").click(function() { if (!active) { active = !active; $('#log').everyTime(1000, 'controlled', function() { $.getJSON( "/log/tail/?pos="+pos, function(data) { if (data.msg !=''){ $("#log").prepend(data.msg+'<br/>'); } pos = data.pos; } ) }); } }).end().find('.stop').css("cursor", "pointer").click(function() { if (active) { active = !active; $(this).parents("div"). find('#log').stopTime('controlled'); } }); }); </script> |
Qui fa la feina és $('#log').everyTime(1000, 'controlled', function() qui es que manté el timer. Cada vegada que passa un segon (1000 ms) es crida al la funció del servidor amb la posició que acabam de llegir. El primer cop no tenim aquesta posició i la inicialitzam a zero, d'aquí que necessitem dues cridades a la funció per obtenir el primer log.
Notem com és de simple manipular el json a Javascritp. data té el text que hem d'escriure i la darrera posició de l'arxiu. Si el text està en blanc simplement ens limitam a actualitzar la posició; si hi ha contingut el posarem dins del div amb identificador log que tenim definit dins la plana.
S'hi pot fer molta més: posar-hi més disseny, podríem fer que es retornàs ja informació la primera vegada que es crida, tenir un reset per a que cuan continua el log sols venguin les darreres línies i no tot el bloc, però la idea és la mateixa:
- fer servir un timer
- fer servir ajax enviant la darrera posició on hem arribat
- fer servir seek i tell per posicionar-nos dins l'arxiu
Com és habitual l'exemple ho podeu davallar d'appfusedjango, o directament un svn co http://code.google.com/p/appfusedjango/source/browse/#svn/trunk/tail
Hi trobareu també una petita utilitat anomenada generate_log.py executant-la en una consola escriu línies de text que poden ser llegides per l'exemple.
Traducciones/Translations by apertium
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
Fer massa bona feina
Escrit per Aaloy a 22 de April , 2009 a les 12:03 a.m.
Que amb les eines que et proporciona Django i un ganes de fer les coses bé, seguint els estàndards i fent les webs semàntiques s'obtenen bons resultats de posicionament és una cosa que puc comprovar dia rere dia.
La darrera ha estat una petició d'una de les seccions de l'empresa per a que féssim alguna cosa amb un micro-site que havíem llançat feia uns dies, ja que quan cerques pel nom del client al Google surt el nostre micro-site enlloc de la plana web de la marca principal.
Explicació: la plana principal del client està desactualitzada, té una relació de pes de la plana front continguts nefasta i està maquetada fent servir taules.
Per una part estic content perquè veig que en el que fa a posicionament i indexabilitat feim les coses prou bé, i per altra banda estic sorprès i fins i tot amoinat per la petició de "fer alguna cosa", que demostra una falta de fonaments en una gent que demana aquest tipus de coses.
Per al que tothom seria un avantatge competitiu: sortir el primer a Google, l'han convertit en una altra manera de dir que no fas bé la teva feina. Encara me fa mal la llengua.
Traducciones/Translations by apertium
2 comentaris, 0 trackbacks (URL) , Tags: Informàtica
Traduccions automàtiques
Escrit per Aaloy a 20 de April , 2009 a les 11:15 a.m.
De tant en tant vaig jugant amb el tema de les traduccions automàtiques, m'atreu molt el camp per la seva utilitat, complexitat tecnològica i sobre tot pel que significa a l'hora d'atracar el coneixement i la informació a tothom sense obligar al qui escriu a expressar-se en una altra llengua.
Fins ara els meus dos referents en traducció automàtica eren el motor que fa servir la Generalitat de Catalunya i Internostrum, desenvolupat per la Universitat d'Alacant.
En un d'aquests experiments he arribat al projecte Apertium, un sistema de codi obert per a la traducció automàtica de documents.
Pel que llegeixo està basat en el codi d'Internostrum i està liderat també la Universitat d'Alacant. El que més m'ha agradat però, és veure com universitats, govern i altres organismes s'uneixen per al finançament d'un projecte de codi obert del qual tothom en port sortir beneficiat. La gent que fa investigació pot tornar a la societat el resultats de la seva investigació i al mateix temps els usuaris podem implicar-nos en el projecte, encara que sigui de beta-testers.
He posat l'enllaç de les traduccions al blog. M'ha impressionat la qualitat de les traduccions que aconsegueix el motor. Estaria molt bé poder-li dir dins el codi html que hi ha parts que no ha de traduir, però tot i això, els resultats crec que parlen per si sols.
Gent d'Apertium la meva enhorabona i moltes gràcies pel vostre esforç!
Traducciones/Translations by apertium
3 comentaris, 0 trackbacks (URL) , Tags: Informàtica
Carregant imatges
Escrit per Aaloy a 19 de April , 2009 a les 11:35 p.m.
Normalment quan treballam amb imatges amb Django ho feim des del punt de vista de disseny, és a dir, posam les imatges al directori on s'han de servir i per avall. Potser a vegades hem fer servir quelcom com el Django Photologue per a tenir les fotografies més estructurades dins la nostra aplicació.
Què passa però, si el que volem és carregar les fotografies des d'un script a la nostra base de dades, o quan ens trobam que la informació no ve pels canals habituals d'una imatge que es puja mitjançant un formulari.
Aquest és el cas que tractarem en aquest apunt. Tenim una imatge que ens arriba codificada en base64 i el que volem és afegir-la amb un petit comentari a la nostra aplicació.
El model que farem servir és tan senzill com això:
1 2 3 4 5 | from django.db import models class Photo (models.Model): image = models.ImageField(upload_to='photos') comments = models.TextField() |
La imatge ens ha arribat com a una cadena de text. El contingut ho podeu trobar al subversion del projecte appfusedjango.
El primer que hem de fer es decodificar la imatge, després crearem una instància de la classe Photo, li assignarem el contingut, el comentari i guardarem. Fins aquí supòs que tothom d'acord.
El problema, però, és que ImageField suposa que li passarem una objecte del tipus File i nosaltres el que tenim és una cadena de text. Necessitarem per tant simular aquest tipus de dada de manera que puguem tractar amb informació que no vengui directament d'un fitxer de text. Ni més ni manco el ContentFile. Aquesta classe que podem trobar a django.core.files.base el que fa és precisament això.
Una altra de les coses que hem de fer és guardar la imatge i assignar-li el nom. Per fer això haurem de crear el nostre objecte Photo, guardar la imatge i després guardar-ho tot a la base de dades.
Anem a veure com quedaria:
>>>import base64 >>>from django.core.files.base import ContentFile >>>from sample.models import Photo >>># ja tenim tot el necessari >>>raw_data = base64.b64decode(open('test/encoded_logo.b64').read()) >>># acabam de llegir les dades, podrien arribar directament >>>foto = Photo() >>>foto.image.save('the-image-name.gif', ContentFile(raw_data)) >>>foto.comments = "Django & Python rules!" >>>foto.save()
El pas del 'image.save' és necessari perquè Django no guarda les imatges per defecte dins la base de dades sinó al sistema de fitxer (de fet podem guardar-ho allà on ens vengui de gust gràcies a les possibilitats del custom storage) així que necessitam definir tant el nom de la imatge com les dades. A la definició del camp ImageField ja li hem dit que voliem deixar les imatges a la carpeta photos que estarà dins el directori que tinguem definit com el nostre MEDIA_ROOT.
El projecte que he pujat serveix per demostrar la idea. Per provar-ho basta fer un
$ python manage.py shell
des del directori del projecte imatges per a convèncer-vos que la cosa funciona veient com es van creant les imatges dins la carpeta media/photos/ del projecte.
Traducciones/Translations by apertium
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
Nou ressaltat de sintaxis pel blog
Escrit per Aaloy a 11 de April , 2009 a les 5:24 p.m.
Fins ara Trespams tenia un ressaltat de sintaxi basat en Javascript, el que feia que no resultàs molt natural escriure apunts amb molt de codi font, ja que significava tenir que posar codi html dins el markdown per tal de marcar aquell tros de codi com a ressaltable pel Javascript.
Com a part de les modificacions he canviat això pel ressaltat basat en Pygments.
Aquest plugin permet fer servir tota la potència de Pygments per al ressaltat, podem resaltar HTML, plantilles Django, Javascript, Java, gairebé qualsevol cosa, i a més fent servir una sintaxi molt més natural, basta afegir un SheBang típic de Unix per a indicar el llenguatge.
La implementació està pensada per a no generar el codi HTML des de Markdown cada vegada, sinó que es guarden dues versions, una amb el codi original i l'altra amb el codi convertit a HTML i ja renderitzat amb els plugins. Això fa que el guardar l'apunt sigui un poc més lent (ha de convertir, reindexar i guardar) però la plana es pot mostrar molt més ràpidament. Optimització prematura? Potser sí, però tanmateix és d'aquelles coses que consideraria una millor pràctica.
El canvi fa que el codi antic no aparegui ressaltat, a poc a poc ho aniré canviant així com vagi revisant els apunts. El que no fa (crec) és trencar res, manté el codi dins un <pre> però no ho ressalta.
Traducciones/Translations by apertium
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
Django regroup
Escrit per Aaloy a 10 de April , 2009 a les 7:36 p.m.
He fet quatre cosetes al programari del blog, per tal de mirar de passar al màxim la validació del w3c, encara tenc problemes amb els pre que em genera el markdown dins paràgrefs i que no passen la validació, però al manco ara la plana es veu prou bé amb Konqueror.
Fent neteja m'he trobat amb la necessitat de refer la jerarquia de l'històric d'apunts. No era gens neta i com que ara el blog té un menú prou potent, he decidit posar molta cosa que estava al lateral com a opció del desplegable.
Per fer la jerarquia d'articles el que es ja el primer de tot és obtenir la llista d'arxius. Això ho feim cridant un tag creat ad-hoc pel blog
{% get_yearly_archive as archive_list %}
que el que fa és executar
Entry.objects.current_active().dates('pub_date', 'month', order='DESC')
i posar-ho a una variable que pot ser usada a la plantilla.
Amb aquest tag obtenim la llista de mesos en els que hi hem fet apunts. Un element d'aquest llista és per exemple:
datetime.datetime(2008, 2, 1, 0, 0)
Com podem veure és un tipus datetime de python i com a tal podem obtenir-ne fàcilment l'any objecte.year o el mes objecte.month.
El que volem, com dic, és fer una jerarquia, és a dir, tenir una cosa com:
- 2009
- Abril 2009
- Març 2009
- 2008
- Desembre 2008
Això normalment duria força feina, però és aquí quan hom veu que Django està pensat per als reptes de la vida real, ja ve amb un template tag predefinit que ens permet fer agrupacions, el regroup
Donada una llista ordenada regroup ens crea una estructura de dades que contindrà els elements pels quals volem fer el grup i dins aquests els element de la llista que tenen aquest element.
En el nostre cas hem posat l'historial dins una variable anomenada archive_list, que recordem és una llista de datetime. Farem
{% regroup archive_list by year as historial_list %}
Amb això hem creat la nostra estructura de dades. Fixem-nos que l'exemple que duu la documentació de Django diu que regroup té com a paràmetre una llista de diccionaris. És part de la gràcia del tipat feble, pel que fa al funcionament de la funció l'estructura datetime es comporta com espera l'iterador groupby que és el que fa servir internament.
Podem simular-ho perfectament a la consola de iPython
1 2 3 4 5 | >In [43]: p = itertools.groupby (x, lambda z: z.year) >In [44]: for i in p: > ....: print i[0] > ....: for j in i[1]: > ....: print j |
Ja tenim l'estructura de dades, així que ara sols quedar recorre i presentar la informació tal com la volem. Per això cal tenir en compte que la nostra estructura defineix la variable grouper que fa referència al valor del camp pel qual estam fent l'agrupació
1 2 3 4 5 6 7 8 9 10 11 12 | {% for year in historial_list %} <li><span class="dir">{{year.grouper }}</span> <ul> {% for d in year.list %} <li><a href='{% setting "BLOG_ROOT" %} {{ year.grouper }}/{{d|date:"m" }}/' class='menu_content'> {{ d|date:"M Y" }}</a> </li> {% endfor %} </ul> </li> {% endfor %} |
Com és habitual, és més llarg d'explicar que de fer.
Traducciones/Translations by apertium
0 comentaris, 0 trackbacks (URL) , Tags: Python Django
Ubuntu 9.04 per PPC
Escrit per Aaloy a 09 de April , 2009 a les 2:59 p.m.
Entre robiol i robiol (ja veus no sóc de panades!) em vaig posar a actualitzar el PPC. Volia ser conservador i anar cap a la versió 8.10 d'Ubuntu, però com sempre el PPC ha resultat ser una capsa de sorpreses.
L'actualització em va deixar amb un sistema on el xinerama no funcionava, gairebé sense dreceres de teclat, el kded ben mort i un refresc de pantalla desesperant. Ni reconfigurant pantalla ni res, massa dependències a resoldre i tot plegat un desgavell.
Mentre amb el portàtil davallava la imatge per tornar-ho a deixar tot estable, vaig pensar en la dita de from the lost to the river que traduït del bilingüe al català, ve a dir alguna cosa així com tanmateix ja ballam i vaig posar a fer up
sudo update-manager -d
Quatre hores o cinc després ja ho tenia tot llest. El resultat és que estic escrivint aquest apunt des de el Gnome amb Xinerama funcionant i configurat des de l'entorn gràfic.
La mala notícia: que sols funciona el Gnome, l'entorn Kde no fa el refresc de pantalla bé i tampoc configura el Xinerama. El darrer no em preocupa gaire, estava dispost a prescindir del Xinerama, però els problemes fan que el Firefox sigui completament inusable, els quadres d'entrada de dades apareixen en negre.
En altre aspecte dir que aquesta versió (al manco per PPC i amb el Gnome) dóna tota la sensació de ser més ràpida que l'anterior. Així que ara per ara toca tonar a Gnome una temporadeta. Tanmateix també és un magnífic entorn.
Traducciones/Translations by apertium
1 comentari, 0 trackbacks (URL) , Tags: Informàtica Linux
Aigua d'abril
Escrit per Aaloy a 07 de April , 2009 a les 8:12 p.m.
Avui aprofitant que plou convendria que més d'un deixàs a casa el paraigües i és fes una bona remullada, a veure si li fa profit.
Podrien començar els defensors del bilingüisme hipòcrites que diuen bilingüisme quan realment volen dir monolingüisme castellà, fent que cada cop més ens trobem discriminats en la nostra terra i en la nostra cultura.
Pareix que també li faria profit al senyor Zapatero, ja que pareix que d'aigua d'abril potser no n'està sobrat si ens hem de fixar en alguns anomenaments recents.
Mentre l'aigua cau per tothom seguiré demanant-me el perquè quan es volen tapar altres problemes, els mateixos de sempre tornen a fer bandera d'un problema que no és tal, i en el perquè hi ha gent que els hi fa el joc.
Traducciones/Translations by apertium
0 comentaris, 0 trackbacks (URL) , Tags: General
Comentaris funcionant (esper)!
Escrit per Aaloy a 04 de April , 2009 a les 12:26 a.m.
Gràcies a Hugo me n'he assabentat que la darrera actualització del blog havia fet malbé el sistema de comentaris.
He pujat una nova versió sense el codi de depuració que feia que els comentaris no es poguessin processar ja que hi havia un punt de ruptura :(
Bé, res greu, coses de les actualitzacions a les males hores del vespre. En Pau també m'ha passat una incidència amb la visualizació del calendari amb Firefox 3.5. Pau, d'això se'n diu viure al límit!
Encara he de netejar molts divs innecessaris de l'anterior disseny. Vull jugar també amb algunes APIs de llocs socials i integrar-les, una de les primeres segurament serà la de Delicius.
Com que a mi també m'agrada viure perillosament estic aprofitant l'edició del blog per provar les versions de desenvolupament de Netbeans per Python. Estic tirant de les construccions del Hudson i provant-ho damunt el PowerPC.
No puc comparar-ho amb l'Eclipse perquè tanmateix damunt el PowerPC com ja he contat l'Eclipse no va gens bé, així que ja no hi ha comparació possible.
Res, que si algú s'anima a posar un comentari donaré per tancat el bug!
Traducciones/Translations by apertium
8 comentaris, 0 trackbacks (URL) , Tags: Python Django
Nou disseny
Escrit per Aaloy a 01 de April , 2009 a les 11:02 p.m.
Bé, dir nou disseny a la nova imatge de Trespams no és dir molt. Ni tan sols diria que és un disseny :-P
Però bé, la idea és anar cap a un disseny molt més minimalista que l'anterior, on sigui un poc més bo de fer afegir coses sense tenir que preocupar-se per si destroçarà massa cosa o no.
Encara queda fer molta neteja, però ara aquest blog té un disseny mínim: el que ve de fàbrica amb blueprincss i sols hi ha alguns retocs per deixar les coses un poc més col·locades i accessibles.
Els menús estan manllevats de Free CSS Drop-Down Menu Framework amb algunes petites adaptacions al css per a que es pugui servir des de un directori distint a l'original.
Es podria dir que estic refactoritzant el blog. Per ara el que vull és anar fent neteja i que tot funcioni igual que abans. Després quedarà llevar les parts que ja no es fan servir, per acabar anar afegint el nou.
Traducciones/Translations by apertium
0 comentaris, 0 trackbacks (URL) , Tags: Informàtica
