April 9th, 2010

Asynchronous send_mail() in Django by Selwin Ong

Django, our web development framework of choice provides many useful functions, send_mail() being one of them which we frequently use.

Though convenient, send_mail() in Django is a synchronous operation – meaning Django will wait for the mail sending process to finish before continuing other tasks. This is not usually that big of a deal if the mail server Django is configured to use is located in the same site (and has low latency), but in cases where the mail server is not located in the same cloud, this could give the impression that your website is slow, especially in sites with relatively slow internet connectivity (like Indonesia).

Consider a really common scenario where an application automatically sends an email verification message to a newly registered user. If configured to use a third party SMTP server like Gmail, the email sending process takes close to half a second if our app is located in Jakarta. This means that we are adding close a half a second of latency before rendering a response to the user, making our app look sluggish (in reality the user creation process itself takes less than 50ms).

So one of our engineers Gilang wrote a simple wrapper around Django’s send_mail() to perform the task asynchronously using Python’s threading.

class EmailThread(threading.Thread):
    def __init__(self, subject, body, from_email, recipient_list, fail_silently, html):
        self.subject = subject
        self.body = body
        self.recipient_list = recipient_list
        self.from_email = from_email
        self.fail_silently = fail_silently
        self.html = html
        threading.Thread.__init__(self)

    def run (self):
        msg = EmailMultiAlternatives(self.subject, self.body, self.from_email, self.recipient_list)
        if self.html:
            msg.attach_alternative(self.html, "text/html")
        msg.send(self.fail_silently)

def send_mail(subject, body, from_email, recipient_list, fail_silently=False, html=None, *args, **kwargs):
    EmailThread(subject, body, from_email, recipient_list, fail_silently, html).start()

To use this small wrapper simply put django_asynchronous_send_mail to your Python path and import it as send_mail():

try:
    from django_asynchronous_send_mail import send_mail
except:
    from django.core.mail import send_mail

The syntax is the same as Django’s built in send_mail() so you don’t need to change anything. It also supports HTML email:

send_mail('Subject here', 'Here is the message.', 'from@example.com', ['to@example.com'], fail_silently=False, html = '')

The full source code is available at GitHub. Obviously, this is a very simple wrapper aimed only to make Django send_mail() behave asynchronously, if you want more advanced featuers like mail queuing or scheduling you should look at other alternatives such as Django Mailer.

February 5th, 2010

Running Django with MySQL on Snow Leopard by Selwin Ong

Getting Django (or Python) to play nice with MySQL on Apple’s Mac OS X 10.6 Snow Leopard is really easy:

  1. Install MySQL. You can get the DMG from MySQL’s official download site (make sure you get the 64 bit version because Snow Leopard runs Python in 64bit)
  2. Type the following commands into terminal and you should be all set:
PATH=/usr/local/mysql/bin:$PATH
sudo easy_install mysql-python

Assuming that you already have Django setup properly and configured to run using MySQL, all you need to do is run manage.py runserver

If you run into errors similar to this, you are probably running MySQL in 32 bit, upgrading to 64bit of MySQL should fix this (this happened to me when I upgraded my OS from 10.5 Leopard to 10.6 Snow Leopard):

Unhandled exception in thread started by 
Traceback (most recent call last):
  File "/Library/Python/2.6/site-packages/django/core/management/commands/runserver.py", line 48, in inner_run
    self.validate(display_num_errors=True)
  File "/Library/Python/2.6/site-packages/django/core/management/base.py", line 249, in validate
    num_errors = get_validation_errors(s, app)
  File "/Library/Python/2.6/site-packages/django/core/management/validation.py", line 22, in get_validation_errors
    from django.db import models, connection
  File "/Library/Python/2.6/site-packages/django/db/__init__.py", line 41, in 
    backend = load_backend(settings.DATABASE_ENGINE)
  File "/Library/Python/2.6/site-packages/django/db/__init__.py", line 17, in load_backend
    return import_module('.base', 'django.db.backends.%s' % backend_name)
  File "/Library/Python/2.6/site-packages/django/utils/importlib.py", line 35, in import_module
    __import__(name)
  File "/Library/Python/2.6/site-packages/django/db/backends/mysql/base.py", line 13, in 
    raise ImproperlyConfigured("Error loading MySQLdb module: %s" % e)
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module: dynamic module does not define init function (init_mysql)

If, for some reason you prefer to stick with 32bit MySQL, you can also tell Python to run in 32bit mode by typing the following command into terminal (source):

defaults write com.apple.versioner.python Prefer-32-Bit -bool yes

To switch back to running Python in 64bit:

defaults write com.apple.versioner.python Prefer-32-Bit -bool no

Hope this bit of info helps some of you Django/MySQL developers out there :).

December 24th, 2009

Merry Christmas and Happy New Year 2010 by Joe

November 6th, 2009

Simulating Slow Internet Connection for Website Performance Testing by Gilang Chandrasa

I joined this army at November, 2nd 2009, so this is my first week in this basecamp.
My name is Gilang Chandrasa, and I’m one of UI web developer.

What I want to show you right now is how to simulate slow internet connection.
Why?

  • Checking AJAX functions in slow connection
  • Measuring if my website is still acceptable in slow connection

For windows user, you can use Firefox add ons called Firefox Throttle.
Firefox Throttle only available for windows, if not this would be a great plugin to have on OS X and Linux.

For *nix user, you can rely on tool caled iprelay.
Ubuntu user can install this tool with this command :

$sudo apt-get install iprelay

To simulate 56Kbps internet connection, type this in your terminal :

$iprelay -b 56000 8001:localhost:80

When you type this address http://localhost:8001/ in your browser, you’ll have 56Kbps connection to your localhost.

October 30th, 2009

Speeding Up Your Website in 5 Minutes (CSS Sprites) by Selwin Ong

In the first article of our website optimization series we discussed about the importance of reducing page load times by compressing text based files served by our website.

I would like to once again stress the importance of building a highly optimized website, this time by highlighting some facts presented in the Velocity 2009 performance & scalability conference. In this conference Shopzilla, an online price comparison website shared their findings that increasing their page load times from 4-6 seconds to 1.5 seconds increased their conversion rate from 7 to 12%!

Reduced page load time leads to increased revenue and page views

Image courtesy of artzstudio

If in the first article we showed you how to reduce page load time by decreasing the number of bytes needed to be moved across the network, now we will tackle this issue from a different angle – reducing the number of items that need to be loaded. Each element in a web page (image, icons, external JavaScript and CSS files) represents a request that needs to be served by the server. The less items that need to be served, the faster the load time, plain and simple.

A popular technique to minimize the number of server requests is called Pingdom’s website testing tool that shows how quickly a page loads.

The first page (with CSS sprites) is rendered in 0.9 seconds, while the second page (regular icons) is rendered in 2.4 seconds – quite a big difference! Furthermore, if we look closely, the image sprite is only 4.96 KB big, while the total size of 8 different icons is 9.72 KB so not only CSS sprites reduce the number of HTTP requests, but it also reduces the aggregate file size.

Using this technique is really easy:
1. Visit css-sprit.es
2. Upload the images you want to combine
3. After you’re done uploading the images press on the “Create CSS Sprite” button
4. Download the resultant image sprite and CSS codes
5. Paste it into your HTML code

Aside from increasing website performance, you could also use techniques that combine JavaScript animation with CSS sprites to make attractive navigation menus. Smashing Magazine has this excellent write up about CSS sprites that you might want to read.


Copyright © 2017 User Inspired Technology Services.