Category Archives: Uncategorized

Django returning JSON for AJAX requests

In your views.py you can have a page that return JSON data for AJAX request like this:

import json
from django.http import HttpResponse

def ajax(request):
    data = {}
    data['something'] = 'useful'
    return HttpResponse(json.dumps(data), content_type = "application/json")

This would work fine if you fill data your self, but if you getting a data from a model try the following:

from django.core import serializers
def tasks_json(request):
    tasks = Task.objects.all()
    data = serializers.serialize("json", tasks)
    return HttpResponse(data, content_type='application/json')

Setting Up Python and Supervisor on CentOS

CentOS default repository is very limited, and even if you install EPEL you will get old packages, in my case I needed to install Supervisor to manage my Django application, after trying to do it manually and through EPEL I ended up with the following setup.

Install Needed Package

sudo yum install python-setuptools
sudo easy_install pip
sudo pip install supervisor

Install Virtualenv Wrapper

We don’t need virtualenvwrapper to setup Supervisord, but it is convenient to use for Python project, for more info check an older post Managing Python Environments with “virtualenvwrapper”.

To install it we need the following steps:

sudo pip install virtualenvwrapper
vi ~/.bashrc
:
# Add the following 2 lines at the end to .bashrc
export WORKON_HOME=$HOME/.virtualenvs
source /usr/bin/virtualenvwrapper.sh
# end .bashrc change

To activate it logout and login again.

Setup Supervisor

We’ve already installed “Supervisor” globally, but we need to create its configuration, luckily it comes with default config:

echo_supervisord_conf > supervisord.conf
sudo cp supervisord.conf /etc/supervisord.conf
sudo mkdir /etc/supervisord.d/
sudo vi /etc/supervisord.conf
:
[include]
files = /etc/supervisord.d/*.conf
:

Next we need to set “Supervisor” to run automatically every time you restart your machine, we need to create /etc/rc.d/init.d/supervisord with the following content:

sudo vi /etc/rc.d/init.d/supervisord
#!/bin/sh
#
# /etc/rc.d/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord

# Source init functions
. /etc/rc.d/init.d/functions

prog="supervisord"

prefix="/usr/"
exec_prefix="${prefix}"
prog_bin="${exec_prefix}/bin/supervisord"
PIDFILE="/var/run/$prog.pid"

start()
{
       echo -n $"Starting $prog: "
       daemon $prog_bin --pidfile $PIDFILE
       [ -f $PIDFILE ] && success $"$prog startup" || failure $"$prog startup"
       echo
}

stop()
{
       echo -n $"Shutting down $prog: "
       [ -f $PIDFILE ] && killproc $prog || success $"$prog shutdown"
       echo
}

case "$1" in

 start)
   start
 ;;

 stop)
   stop
 ;;

 status)
       status $prog
 ;;

 restart)
   stop
   start
 ;;

 *)
   echo "Usage: $0 {start|stop|restart|status}"
 ;;

esac

Then make sure CentOS knows about it:

sudo chmod +x /etc/rc.d/init.d/supervisord
sudo chkconfig --add supervisord
sudo chkconfig supervisord on
sudo service supervisord start

Sample Supervisor App

Here is a sample of Django App to be controlled and monitored by Supervisor, just put it:

sudo vi /etc/supervisord.d/my_django_cms.conf
[program:my_django_cms]
directory=/var/www/dashboard/www
command=/home/rayed/.virtualenvs/dev/bin/gunicorn apps.wsgi:application -b 127.0.0.1:8080 --workers 8
# UNIX Socket version (better with Nginx)
#command=/home/rayed/.virtualenvs/dev/bin/gunicorn apps.wsgi:application -b unix:/tmp/my_django_cms.sock --workers 8
environment=DJANGO_ENV="prod"
user=rayed
autostart=true
autorestart=true
redirect_stderr=True

After that:

 sudo supervisorctl add my_django_cms
 sudo supervisorctl start my_django_cms

Setting Apache to Proxy to Gunicorn

To add virtual host to Apache that forward dynamic content to Gunicorn:

sudo vi /etc/httpd/conf.d/my_django_cms.conf
NameVirtualHost *:80
<VirtualHost *:80>
    ServerName dj.example.com
    ServerAdmin webmaster@example.com
    DocumentRoot /var/www/my_django_cms/www
    RewriteEngine on
    ProxyPreserveHost On
    RewriteCond $1 !^/(img|css|js|robots\.txt|media|static|s)
    RewriteRule ^(.*) http://localhost:8000$1 [P]
    <Proxy *>
            Order deny,allow
            Allow from all
            Allow from localhost
    </Proxy>
</VirtualHost>

If you have SELinux enabled you might need to apply the following command:

setsebool -P httpd_can_network_connect 1

If you have issues accessing your statics files from Apache it might be SELinux also:

restorecon -Rv /var/www/my_django_cms/

Django Multiple Settings with Single File

Instead of having multiple settings files one for production and one for development and so on, I prefer to use an “if” statement with environment variable:

ENV = os.environ.get('DJANGO_ENV', '')
print "==== Active Env: [%s]  ====" % (ENV)    
if ENV == "dev":
    # DEBUG
    DEBUG = True
    TEMPLATE_DEBUG = DEBUG
else:
    DEBUG = False
    TEMPLATE_DEBUG = False

Then from your “.bashrc” file:

export DJANGO_ENV=dev

PostgreSQL Replication

We will assume we have two servers:

  • Master IP 192.168.100.51
  • Slave IP 192.168.100.52

MASTER

Create replication user “repl”:

sudo -u postgres createuser -P repl
sudo -u postgres psql
> ALTER ROLE repl REPLICATION;

Allow “repl” user to connect from the slave:

$ vi /etc/postgresql/9.1/main/pg_hba.conf
:
host    replication     repl            192.168.100.52/32        md5

Setup replication parameters:

vi /etc/postgresql/9.1/main/postgresql.conf
:   
listen_addresses = '*'
wal_level = hot_standby
max_wal_senders = 1
wal_keep_segments = 5
:

Create a copy of the database and copy to the slave:

service postgresql stop
cd /var/lib/postgresql/9.1
tar -czf main.tar.gz main/
service postgresql start
scp main.tar.gz rayed@slave:

SALVE

Restore data from master:

service postgresql stop
cd /var/lib/postgresql/9.1
rm -rf main   # BE CAREFUL MAKE SURE YOU ARE IN SLAVE
tar -xzvf ~rayed/main.tar.gz
rm /var/lib/postgresql/9.1/main/postmaster.pid

Create recovery.conf file in data directory:

vi /var/lib/postgresql/9.1/main/recovery.conf
:   
standby_mode = 'on'
primary_conninfo = 'host=192.168.100.51 port=5432 user=repl password=repl_password
:   

Edit postgresql.conf:

vi /etc/postgresql/9.1/main/postgresql.conf
:
hot_standby = on
:

Start the slave server again, and check the log file

service postgresql start
tail -f /var/log/postgresql/postgresql-9.1-main.log 

For more info:

Login to PostgreSQL without typing a Password

If you to connect to PostgreSQL without typing a password, you can do it by having your password in the file “.pgpass”.

The file reside in your home directory and must be readable to you only:

touch ~/.pgpass
chmod 600 ~/.pgpass

The format is simple:

hostname:port:database:username:password 

For example:

*:*:my_database:rayed:my_hard_password

The “*” means any host using any port.

This of course will work for “psql” and other tools to like “pg_dump”.

Django “render” vs “render_to_response”

Summary: Always use render and not render_to_response

In Django you have more than one way to return a response, but many times I get confused between render and render_to_response, render_to_response seems shorter, so why not use it!

To explain let’s assume simple posts page:

def article_list(request, template_name='article/list.html'):
    posts = Post.objects.all()
    # DON'T USE
    return render_to_response(template_name, {'posts': posts})

In this example you will be able to access “posts” in your template, but unfortunately you will not have access to other important variables from other Middlewares, most importantly: user, csrf_token, and messages. To make “render_to_response” pass all these parameters you must send a “context_instance” like this:

return render_to_response(template_name, {'posts': posts}, context_instance=RequestContext(request))

Not so short after all, compare to “render” version:

# USE THIS :)
return render(request, template_name, {'posts': posts})

In fact “render” is always shorter than “render_to_response”, even without the “context_instance”:

return render(request, template_name, {'posts': posts})
... vs ...
return render_to_response(template_name, {'posts': posts})