Django model history with django-reversion

October 13th, 2009

I’m currently working on a django project and I needed to track all changes to a model and provide a log showing what has changed (like a wiki).

I’ve found three extensions/libs that apparently could do the job for me (fullhistory, django-history and django-reversion) so I decided to test them, but because of the lack of structure/documentation of the other two I tried just the last one.

django-reversion

(http://code.google.com/p/django-reversion/)

It has a good documentation, integration with the admin and the most important for me a low level api, as I am not using the admin app for this project.

The installation went pretty well (svn co http://django-reversion.googlecode.com/svn/tags/1.1.2/src/reversion to your PYTHONPATH, add the reversion app to your INSTALLED_APPS in settings.py and the usual python manage.py syncdb).

To track the changes of a model you must register it with the reversion framework (importing reversion and calling reversion.register(YourModel)).

Reversion provides some ways for creating revisions of your model and the docs recommend that you choose one of them to use in your project. I chose the MiddleWare method because it seemed the better option for our project, but you should look the reversion documentation and decide which one is the best for you.

After registering the model and installing the MiddleWare no more changes are needed, whenever I save a model a new revision is created on the database. Another cool feature is the follow argument when registering a model. That way you can specify a ForeingKey/ManyToMany field to follow. This means that when you save the model a new revision is created with all “followed” fields in its current state. It’s very useful. See the docs for an example.

The only thing that’s not so clear for me is: what happens if I delete a field from a model that’s registered within reversion? Can you still restore its versions?

Creating a tweet gadget for Google Wave

October 10th, 2009

This week bani sent me an invite for trying Google Wave. It’s a great tool and if it remains as open as Google says it will I think it can really change the way we communicate over the internets. I mean, it’s much more flexible than e-mail and it takes collaboration to another level. But, as I said, IMO the “key for success” in this case is to stay open and to support the creation of other servers and implementations(as PyGoWave [which deserves a blog post]).

But enough of cheap talk, I’ll show you the code.

My first “useful” piece of code for Wave is a Tweet Gadget. It’s a simple Google Gadget that takes advantage of the Wave extensions for interacting with the Wave user. What the gadget does is very simple, it takes a tweet id and using the Twitter API it places the tweet inside the Wave. It’s a simple way to quote a tweet.

I must say that the original idea is not mine, it’s rbp’s idea. We were chatting using Google Wave and he wanted to quote a tweet. That’s how we started looking ways of doing it.

Stateless gadget

I started writing a simple gadget that using the Google Gadgets API makes a request using the Twitter API and shows the tweet in the wave. The problem of this first version was that it does not keep the state, so if you reload/rejoin the wave, you won’t see the tweet, but instead you will see the text box for entering the tweet id.

In this first version you can see how to make a JSON Async Request using the Google Gadgets API. It’s very simple, all you need to do is to set the parameter gadgets.io.RequestParameters.CONTENT_TYPE to gadgets.io.ContentType.JSON and then call gadgets.io.makeRequest(url, callback, params) where callback is a function that receives the JSON object.A very simple example:


function myCallback(obj) {
jsondata = obj.data;
// access the attributes as jsondata['key']
// ...
}
function makesJSONRequest(url) {
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
gadgets.io.makeRequest(url, myCallback, params);
}

Adding state

Until now the gadget is a simple Google Gadget as it does not use any feature of Google Wave. Also it’s not so useful because it can’t keep the tweet id when you leave the Wave. And worse, people will never see the tweet you quoted. One of the main differences between simple Google Gadgets and Wave Gadgets is their ability to keep, set and change state. By state I mean information. You can keep user preferences, a game score or a tweet id (or even a tweet).

I decided that the easiest way was to store the tweet as it will appear in the wave (with HTML entities and everything). The new version will keep the tweet information when the user enters the tweet id, so everybody in the wave can see the quoted tweet.

You can see the Gadget code to understand how state works in Google Wave, but what’s most important:

  • use a callback (with wave.setStateCallback()) to be aware of state changes
  • wave.getState() returns an state dict-like object which you can set and get information from
  • use wave.getState().get(’key’) for getting an information
  • and wave.getState().submitDelta({’key1:’ value1, ‘key2′: value2} for setting information

And that’s it. It’s very simple, hope you enjoy it :)

Transparência HackDay

October 2nd, 2009

“Two days for hacking the Brazilian politics”

This weekend (October 3rd and 4th) will happen the first “Transparência HackDay” (”Transparency HackDay” in english), a free and open hacking event with focus on bringing together hackers, activists, managers and people with ideas to make government information/public data more accessible for everyone using and writing web tools.

I’m attending and one of my ideas is to hack CET (Companhia de Engenharia de Tráfego / Traffic Engineering Company) data and make them available. The idea is to improve a crawler I wrote (in python ;) ) that downloads and stores data about the traffic in São Paulo every 30 minutes from the “traffic now” CET website (as they don’t store it [or at least don't provide anything]).

More information about the HackDay (in portuguese):
http://www.slideshare.net/esferamobi/transparencia-hackday-proposta

Car-addiction has a cure

September 22nd, 2009

car-addiction has a cure

São Paulo, September 22, World Carfree Day.

Av. Sumaré.

Pictures

http://www.flickr.com/photos/brunogola/3944808600/
http://www.flickr.com/photos/brunogola/3944024499/
http://www.flickr.com/photos/brunogola/3944018159/

São Paulo Intermodal Challenge 2009

September 18th, 2009

Yesterday, September 17th, occurred the São Paulo Intermodal Challenge that happens yearly since 2006.

The following table shows the results:

Results

Modal Time min Cost (R$) CO2 (kg)
Pedestrian 92 0 0
Pedestre running 66.30 0 0
Bike courrier 25.30 0 0
Biker (begginner) 66 0 0
Biker (alternative route) 38.20 0 0
Biker 37 0 0
Folding bike + subway 68 2.40 0.24
Fixedgear bike 22.33 0 0
Motoboy 42.28 1.50 1.44
Motorcycle 25 1.50 1.81
Car 82 15 2.63
Bus 71.20 2.30 0.24
Subway+Train 84 3.70 0
Train+Bus 89 3.70 0.21
Bus+Subway 109 3.70 0.24
Train+Bus+Subway 99 2.55 0
Scooters 58 0 0
Wheelchair+public transportation 108 3.70 0.21
Hellicopter 33.50 2.600 3.75?

I’ll post more details later.

São Paulo Python User Group – May Meeting

May 16th, 2009

Every month the GruPy-SP members get together to discuss, chat and/or code.

This month we will meet to watch/present some lightning talks and to talk about our participation at the Fórum Internacional de Software Livre (FISL 10).

The meeting will be hold at the SP HackLab, May 23. More details (in pt-br): GruPy-SP wiki.

See you there :-)

Cof cof… dust… new stuff

March 16th, 2009

I’ll start mixing english and portuguese posts. And I’ll probably start writing about bicycles and other stuff, not only about my geek side (dunno if it’s possible) :-P

Thinking about changing the layout too, this blue-wordpress-default is boring (maybe it’s just me :-])

I’m starting a personal wiki too (http://wiki.brunogola.com.br/).

Probably updating my wordpress installation as well.

CHDK: hacking my camera

December 5th, 2008

I have a Canon A-640 that I rarely use, partially because it’s flash is broken. Now I found a new use for it, a hackable device :D

With CHDK (Canon Hack Development Kit) I can write my own scripts (in LUA or BASIC) to control the camera functions. It also enables new features and improve old ones. Really nice free software project :)

And for hackers, it’s well documented (including the source-code). I’ll try it better and post some results here (with pictures and some code I hope :) )

HP 2133 and Ubuntu

October 29th, 2008

Last week I got a HP 2133 mini notebook for me to use on presentations, college, meetings, events, etc. It’s a very nice toy with 1Gb RAM, a 1.2 GHz VIA Processor, 120Gb of storage, Wifi and bluetooth. Well, it’s very handy and the keyboard is amazing… except for the key, that is a little smaller than the on in my “official” notebook, and I always try to press it in the wrong place :-P

But… I’ve spent a lot of time to make it work with my Ubuntu. Why? Mainly because of the freakin’ VIA proprietary video driver. So I decided to write here some tips about how to get Ubuntu working on the 2133 (after trying to configure the xorg.conf for 3 hours because I hadn’t made a backup of the one that was working :P ).

The problem I have is that the desktop is bigger than the screen. Oh, you say, it’s just the Virtual xorg.conf Option.

IT’S NOT. Damn it!

Thanks to VIA there is a driver option called PanelID. This option is “well documented” in the README file.

The first thing you need to do is to tell the driver that your PanelID is 17. Why? I really don’t know. PanelID 17 means, accordingly to the README, that your display (or your Panel) resolution is 1024×600. The problem is that I want my resolution to be 1280×768 (which is supported by 2133). Anyway, using option “PanelID” 17 solves the problem partially, the desktop isn’t bigger than the screen anymore.

BUT… it thinks that your resolution is 1024×600 (because of the PanelID option, probably), so try to imagine what a 1280×768 desktop looks like in a 1024×600 display (or panel, whatever). The result is that you can see 3/4 of your Desktop, but your pointer “sees” the “panel” borders (i mean, it can’t go any longer than the screen limits).

To solve this problem you need to tell the X server that you have a Virtual display of 1024×600 (yes, you’re lying!!!) so it will arrange your 1280×768 desktop inside this virtual display of 1024×600. To do this you need to add the line

Virtual 1024 600

in the Display subsection of the Screen section.

Your xorg.conf will look like this (the relevant sections only):

Section “Device”
Identifier “via-P4M900 Device 0″
BoardName “Chrome9 HC IGP”
BusID “PCI:1:0:0″
Driver “via”
Option “Monitor-LCD” “HP-2133 LCD”
Option “PanelID” “17″
Option “NoDDCValue”
EndSection

Section “Screen”

Subsection “Display”
Depth 24
Modes “1280×768-60.0″
Virtual 1024 600
EndSubsection

EndSection

If you have any trouble with the video (or anything) trying to install Ubuntu on the HP 2133 Mini, leave a comment and I promise I’ll TRY to help :-D

Nokia Code Camp São Paulo

October 27th, 2008

Last Friday (Oct 25) I’ve attended to the Forum Nokia Code Camp here in São Paulo. I must admit that the main motivation to go was that the place was very near my house :-P

After finding out that rbp, lhonda and Luiz Irber (friends from our local Python User Group) were attending too I thought that it’d be a nice event. At least we could talk about GruPy-SP plans…

Anyway, I went to the hotel and after watching the three presentations (speaking about Nokia Serie60, Python and mobile development) the fun really started. 4 hours to develop the coolest mobile application in the world :-P

The prize was two E71 (the “new” Nokia Smartphone) for the “winner” application, so we decided to code in pairs. Me and rbp, after talking about our ideas, decided to write a musical instrument using the N95 accelerometer.

The first two hours of “development” actually we spent trying to find a proper way to transfer files to our cellphones (the S60 SDK is Windows only…). Then, with the “bluetooth easiest method” for transferring the app working, we started trying to find out how to interpret the accelerometer data. It worked as expected. Then we needed to play a sound (as it was a musical instrument). Easy, Python for S60 is very intuitive, the API is very High Level. Looking to the reference guide there was something like:

from audio import Sound
Sound.open(”file.mp3″).play()

Just as I expected… except that there wasn’t any sound coming from the freakin’ phone’s speaker. There was forty minutes left to the end of the competition and all we had was a soundless musical instrument, not very useful.

Ok, plan B. I started looking to some old code in my N95 and found a bluetooth webcam prototype. Rbp had an idea of making the webcam “crash” with a movement (using the accelerometer). And then we made it.

It’s a funny application and, as I said to rbp, as programmers we are great comedians. We presented the webcam in the stage and people seemed to like us (the app or the comedians? I really don’t know :-) )

Well, me and rbp won a Nokia E71 (each), it’s a very nice (and THIN) smartphone, I don’t like phones with qwerty keyboards, but this one is really cool (thin, small and almost comfortable to type).

10/27/2008

Thanks Forum Nokia! :-)