Wednesday, November 23, 2011

Sort a dictionary of dictionaries in Python

Sounds like a big challenge? not at all!

Problem description:
Suppose you have a dictionary of dictionaries. Every key has a dictionary assigned to it, for example:
mydict = {'hello':dict(key1='val10', key2='val20', key3='val30'),
              'world':dict(key1='val11', key2='val21', key3='val31'),
              'howru':dict(key1='val12', key2='val22', key3='val32')}

and your goal is to get a list of mydict "inner" dictionaries, ordered by key2.

A solution for example:
from operator import itemgetter
mydict_values = mydict.values()
mydict_values.sort(key=itemgetter("key2"))

Explained:
mylist.values() gets the list of values from mydict, which is the "inner" dictionaries.
I'm using sort to sort the list of dictionaries, by key, which is looking for item named key2 as the key.

That's all for this time :-)

Tuesday, November 15, 2011

Temporary disposable email address using Gmail

This is very useful for testing registration processes, where you need to register with a new email address every time.
Suppose you have a gmail address:
name@gmail.com .
You can send emails to:
name+2@gmail.com, name+cnn@gmail.com .
The rule is that you can add any alphanumeric characters after the ‘+’ sign.
All emails would be sent to your name@gmail.com account.

Is nice :-)

Thursday, June 23, 2011

Django forms inheritance

I'm using Django forms and needed to create a form for password reset use case.
It turned out that Django already has a built-in form for this operation, but I needed some extra tweaks on it. In addition, I had 2 use cases which required 2 different validations on the form.
Instead of creating 2 new forms from scratch I decided to use Python's inheritance capabilities and produced the following:

class MyFirstPasswordResetForm (django.contrib.auth.forms.PasswordResetForm):
## Override's Django's email field, since I needed a different error message
email = forms.EmailField(label=_("E-mail"), max_length=75, required=True,
error_messages={'invalid': _(u'Please enter a valid email address')})

## My new field
my_hidden_field = forms.CharField(widget=forms.HiddenInput, required=True)

def clean_email(self):
"""
Calling Django's clean_email function, but overrides Django's error message
"""
try:
return super(MyFirstPasswordResetForm, self).clean_email()
except forms.ValidationError:
raise forms.ValidationError(_("This address was not found in our DB - are you sure this is the email address you used to register?"))

def save(self, domain_override=None, email_template_name='registration/password_reset_email.html',
use_https=False, token_generator=default_token_generator):
"""
Overrides Django's save function
"""
## Do some stuff
pass

And this class inherits from it:
class MySecondPasswordResetForm(MyFirstPasswordResetForm):
'''
Inherits "email", "my_hidden_field" and "save" from MyFirstPasswordResetForm
'''
def clean_email(self):
"""
Override just this function.
"""
email = super(MySecondPasswordResetForm, self).clean_email()
## Additonal validations here, specific for MySecondPasswordResetForm

return email


And it saves code duplication, development and testing time !

Monday, April 18, 2011

Django models - order_by CharField case insensitive

Working with Django models, I needed to sort my data by a string (CharField) column:

class MyModelName(models.Model):
   is_mine = models.BooleanField(default=False)
   name = models.CharField(max_length=100)

So I used this python code:
MyModelName.objects.filter( is_mine=1 ).order_by('name')

However, the default sorting is case sensitive, which caused odd results order:

A
B
C
a
b
c

The solution was to normalize the data (change to lowercase) and then sort:
MyModelName.objects.filter( is_mine=1 ).extra( select={'lower_name': 'lower(name)'}).order_by('lower_name')

So now I get this result:
A
a
B
b
C
c

Which is exactly what I need !! :-)

More on Django API "extra" function here.