Friday, December 28, 2007

HowTo: Django Dev Environment on MacOSX Tiger using MacPorts

The Mac uses Python in the OS itself, so messing with the system Python can be risky, and Apple has a bad reputation for compliance with the official Python, because the earlier versions of OSX shipped with broken Python installations, and even recent versions of OSX ship with modified versions of Python.

MacPorts can give you a consistent django dev environment with easy upgrades, but you have to be conscious of which Python you are calling and make sure your PATH variables are set correctly when making scripts, using IDEs, and so on. MacPorts offers a django port, so you could feasibly set up everything through MacPorts, but I set up django with subversion here.

MacPorts

Install MacPorts from the Mac OSX package.

Python Environment and Postgresql

Macports treats each piece of software as a "port," and it downloads the source, compiles, and then installs the software for you. MacPorts also installs dependencies for you, so if you tell MacPorts to install port C, which is dependent on A and B, MacPorts will install A, B, and C.

In order to make sure that your MacPorts has the latest info, update it with:sudo port sync

For Django, we need a DBMS, and I choose Postgresql. We need psycopg to link it to Python, so let's first find out which postgresql, python, and psycopg ports are available:sudo port search postgresqlsudo port search pythonsudo port search psycopg

A little research reveals that, as of this writing, the differences in Python 2.4 and Python 2.5 have necessitated that the MacPorts project separate related ports into those beginning 'py-' for Python 2.4 and 'py24-' for Python 2.5. So since I want to use Python 2.5 with Postgresql, I will need to use py25-psycopg2.

The port maintainer decides the dependencies of the port she maintains, so the dependencies of py25-psycopg2 will determine the version of Postgresql to be installed:sudo port deps py25-psycopg2

Though postgresql82 is the newest version, py25-psycopg2 depends on postgresql81, so that is the one I will go with.

And now the library that allows Python and Postgresql to communicate:sudo port install py25-psycopg2

Technically, this is the minimal set of parts needed for django, but the MacPorts version of Python includes only the essentials, leaving it to the user to add modules, and some of these excluded modules are needed to really use Django. First install py25-hashlib to accommodate Django's authentication module:sudo port install py25-hashlib

Next, install py25-readline if you want the interactive interpreter to be usable at all (backspace, delete, etc.):sudo port install py25-readline

Another recommendation is to install iPython, which is an enhanced Python interactive shell. While I would not bother if I had to manually configure Django to work with iPython, I recommend it here because (1) iPython is multi-platform and (2) Django was modified to call iPython, if found, and only if not found to call the regular interactive shell.

Though postgresql is installed, it is not really set up yet. For the sake of easy management, I want to keep all user databases in /Users/DB/postgresql, so first make that dir:sudo mkdir /Users/DB/postgresql

Now we go to Netinfo Manager to find out what user (and group) MacPorts installed for postgresql. It should be user postgres, but my install resulted in the following, so I give it a password :username: postgres81group: postgrespasswd: agoodpassword

Make PostgreSQL binaries available to user by adding to PATH in ~/.profile:echo 'export PATH=$PATH:/opt/local/lib/postgresql81/bin' >> ~/.profile

Since PostgreSQL will run under postgres81 user, we need to make it own the postgresql directory:sudo chown -R postgres81:postgres /Users/DB/postgresql

Initialize the PostgreSQL master database. We are starting PostgreSQL as user postgres81, so we use sudo to elevate privileges; use su to assume the user we want, then use -c to tell su to execute a command as user postgres81:sudo su postgres81 -c "initdb -D /Users/DB/postgresql"

Now logout and log back in, then create a role (user) in postgres with the same name as the login who will use it:sudo su postgres81createuser -s -P -l

Part of the MacPorts install adds the dir for the MacPorts apps to the PATH:# Setting the path for MacPorts.export PATH=/opt/local/bin:/opt/local/sbin:$PATH

However, when calling python from the command line, you will still get the Tiger default Python 2.3 because the MacPorts Python executable in /opt/local/bin is named python2.5, so make a symbolic link so that a call to 'python' will give you 'python2.5':sudo ln -s /opt/local/bin/python2.5 /opt/local/bin/python

Django source files

Now that Python 2.5 and Postgresql are set up, it is time to install the Django source files. First, use the shell to find the site-packages dir for Python:python -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"

Assuming you set the PATH correctly, the default MacPorts Python 2.5 install should give you:/opt/local/lib/python2.5/site-packages

You can install the django source right there in site-packages, or you can install them in a separate directory and make a link. For my purposes, I want a dir for web dev, and inside it a dir for django, and inside that I want to install the django source code, so let's create that nested dir:mkdir -p ~/Webdev/django/src

Next, move to the source dir and use svn to check out the dev trunk of django in this dir. This command will create a dir containing the dev version. This is the core code of django, and it will be kept separate from the projects that will be created with django:cd ~/Webdev/django/srcsvn co http://code.djangoproject.com/svn/django/trunk/ django-trunk

Create a symbolic link to the django source in the site-packages dir:sudo ln -s ~/Webdev/django/src/django-trunk /opt/local/lib/python2.5/site-packages

Create a symlink to make sure that the Python interpreter can load the django code:ln -s /opt/local/lib/python2.5/site-packages/django-trunk/django /opt/local/lib/python2.5/site-packages/django

On Unix-like systems, first check your $PATH and then create a symbolic link to django-admin.py in a directory on your system path so that you don't have to type the full path when invoking it, so if `echo $PATH` shows that /usr/bin is in your path, you can make a link:ln -s /opt/local/lib/python2.5/site-packages/django-trunk/django/bin/django-admin.py /usr/bin

The sites you make in Django are stored separate from the Django code, and all of this is outside of your public_html or /var/www directories. I choose to keep my projects in the django webdev dir:mkdir ~/Webdev/django/sites/

First project according to Django Tutorial

Move to the sites dir and create a new project:cd ~/Webdev/django/sites/django-admin.py startproject mysite

If postgresql is not running, turn it on and then login to psql:pgstatuspgstartpsql template1

In psql, create postgresql role django to use for django and then create the unicode database mysite with django as owner:create role django with superuser createdb login password 'agoodpassword';create database mysite encoding='UTF8' owner=django;

Run the script to create tables for installed apps listed in settings.py:python manage.py syncdb

This creates the tables needed for your test project. Use psql to take a look. Earlier, you created a superuser with the same name as the MacOSX login you are using, and you created the django user and the mysite database with django as the owner, so you should be able to access and examine the mysite database:psql mysite

Use /dt in psql to describe tables (see all the tables in the database you are using), and use /d tablename to examine individual tables.