Django and pip wheel

26 August 2013 (updated 02 May 2016)

Just a quick heads-up: older Django versions don't work properly if installed via wheel. It's fixed in 1.6 but it's not final yet (right now it's in beta). Edit: Django 1.5.2 has the fix backported from 1.6.

Apparently the older versions of Django list the package data files under the data_files setup.py option and wheel follows the spec to the letter (installs data_files in sys.prefix) while setuptools does not (it treats relative data_files just like package_data entries).

If you switched to wheels already you can fix the template loading with something like this:

import sys
import os

from django.template.base import TemplateDoesNotExist
from django.template.loader import BaseLoader
from django.conf import settings

class SysPrefixLoader(BaseLoader):
    is_usable = True

    def load_template_source(self, template_name, template_dirs=None):
        pkg_name = 'templates/' + template_name
        for app in settings.INSTALLED_APPS:
            try:
                return open(
                    os.path.join(
                        sys.prefix,
                        os.path.join(*app.split('.')),
                        pkg_name
                    ),
                    'rb'
                ).read().decode(settings.FILE_CHARSET), 'sysprefix:%s:%s' % (app, pkg_name)
            except Exception:
                pass
        raise TemplateDoesNotExist(template_name)

And just add module.SysPrefixLoader to TEMPLATE_LOADERS in the settings.

For the staticfiles, use this finder:

import sys
import os
from django import VERSION
from django.contrib.staticfiles.finders import AppDirectoriesFinder, AppStaticStorage

class SysPrefixStorage(AppStaticStorage):
    def __init__(self, app, *args, **kwargs):
        self.app_module = app
        if self.app_module == 'django.contrib.admin' and VERSION < (1, 4):
            self.prefix = 'admin'
            self.source_dir = 'media'

        location = os.path.join(
            sys.prefix,
            os.path.join(*app.split('.')),
            self.source_dir
        )
        super(AppStaticStorage, self).__init__(location, *args, **kwargs)

class SysPrefixFinder(AppDirectoriesFinder):
    storage_class = SysPrefixStorage

And add module.SysPrefixFinder to STATICFILES_FINDERS in the settings.

Locales appear harder to fix (there's no pluggable loader) ...

This entry was tagged as django packaging python