If you develop Django using MySQL on a Mac, you’ve undoubtedly run into the “Not an image file” error for models with image fields. The problem has to do with JPEG support for Mac OS and how it interacts with Python Imaging Library. Diabolically, once you’ve installed PIL with bad JPEG support it seems impossible to fix.
My solution is to use a virtualenv. virtualenv is a python tool to create an isolated Python interpreter on your system, which allows you to control the installed packages without mussing up your main Python installation. It’s good practice to use a separate virtualenv for each project, and if you use Eclipse you usually want one for each workspace
There are, of course, other solutions to this problem (using PostgreSQL is probably one of them). The instructions here are based on this post on DjangoDays.com.
Prereqs
You’ll need to have xCode installed. Also, if you want to use Eclipse, vlku.com has an excellent screencast that covers everything.
Create a “workspace”
The best place to keep the virtualenv for your Django project is right next to your Django code. Create a directory to hold both. This can be just a plain directory, but if you’re using Eclipse make a new workspace first and complete the following steps in that workspace. If you have existing code, drop it in the root of this folder. For this tutorial let’s call the folder “myworkspace” and your project “myproject”.
Set up a Virtual Environment with –no-site-packages
Use easy_install to get virtualenv.
easy_install virtualenv
Change into the ‘myworkspace’ directory and create a new virtualenv. The key here is to use the –no-site-packages argument, which creates a Python that ignores the system packages already installed. We don’t want anything to come over from the system Python in case you’ve already installed a useless PIL.
python virtualenv.py python --no-site-packages
You now have a fresh, Django- and PIL-less Python interpreter at myworkspace/python/bin/python. The directory structure should now be as follows:
- myworkspace + - myproject + - python
Install libjpeg (JPEG Support) system wide
Here’s the key to fixing the problem, and where the DjangoDays.com post really saved my butt. Forget the virtualenv for a second, we’re installing JPEG support system wide.
- Download JPEG support. This little sucker keeps moving around the internet. I used version 6, which is still available here. The project is maintained my the Independent JPEG Group, who are showing version 8 as of this posting.
- Extract the tarball, cd into the resulting folder (in my case, it was called jpeg-6b, and install it with these changes.
cd jpeg-6b cp /usr/share/libtool/config.sub . cp /usr/share/libtool/config.guess . ./configure –enable-shared make sudo mkdir -p /usr/local/include sudo mkdir -p /usr/local/bin sudo mkdir -p /usr/local/lib sudo mkdir -p /usr/local/man/man1 sudo make install
Thanks DjangoDays.com.
Install PIL
Now we’ll install PIL and point it to the correctly installed JPEG Support. This is again lifted from the DjangoDays.com post.
- Download the PIL tarball here.
- Extract it, cd into the resulting folder, and edit setup.py to change these lines:
JPEG_ROOT = none ZLIB_ROOT = none
to this:
JPEG_ROOT = “/usr/local/include” ZLIB_ROOT = “/usr/local/include”
- Install PIL with these commands:
python setup.py build_ext -i python selftest.py sudo python setup.py install
I got 9 errors when I ran selftest.py, but kept going and haven’t seen any indication that the errors are giving me any trouble. Again, thanks DjangoDays.com.
Install Django, MySQL-python, etc.
Here’s a post a did a last year detailing Django installation on Mac OS X. That is, again, not the only way of doing it. The key here is to use the Python interpreter you just created to install Django and all it’s prereqs. You also have a virtualenv specific easy_install. Use it to install any other dependencies.
myworkspace/python/bin/python myworkspace/python/bin/easy_install
Run your project
I’m skipping a lot of steps (and debugging) here, but assuming you’ve got your project set up correctly you should now be able to cd into the ‘myproject’ directory and run the server with the following command:
../python/bin/python manage.py runserver
As a shortcut, you can set an environment variable in the ‘myworkspace’ directory to map the command ‘python’ to /myworkspace/python/bin/python. Better yet, if you’re using Eclipse, use that Python as you’re interpreter, and configure the debugger to run the command for you.