Django Packaging Guidelines
Proposal for packaging guidelines of Django applications and projects.
There is no strong guideline for packaging Django applications and projects for Debian. Existing guidelines for web applications do not fit Django very well.
The goals can be summarized as the best, practical approach to supporting Django web applications out of the box.
Packaging Django Applications
Django applications, despite the name are a Django equivalent to Python package. It's a immutable container of code, templates and read-only web resources (images, scripts, etc). The guide defines:
- Where to install code?
- Where to install templates?
Where to install static files? (as understood by http://docs.djangoproject.com/en/dev/howto/static-files/)
- Where to install documentation? (if any)
Packaging Django Projects
Django projects are containers for applications, settings, templates and resources. They are the practical means of running Django code. The guide defines:
- Where to install code? (urls, settings, etc)
- Where to install project-wide templates? (spanning many applications)
- How do support database configuration and integration?
- Where to store user uploaded content?
- Where to store static read-only files?
Packaging Django Applications
Code, documentation and i18n
For the most part, Django applications differ very little from python packages. This guide recommends that the following components adhere to standard, documented packaging guidelines:
- Python source code
- ReST documentation (built along with the package)
- i18n files, gettext message catalogs
The rationale for this choice is that all Django applications are just python packages and thus should be treated exactly like python packages. Documentation and translation files are already well established and should not diverge for unspecified reasons.
Packaging of templates should follow the same guidelines as packaging the actual source code. This guide recommends that templates should be installed in /usr/lib/python2.*/packagemodule/templates, that is, they should be installed in the "templates" directory relative to the directory with the python package.
The rationale for this choice is:
- Templates are inheritable and should be treated like source code
- It follows common upstream practice
- It simplifies template lookup at runtime (using the default django.template.loaders.app_directories.Loader)
- It removes the necessity to hardcode Debian-specific pathnames in any configuration files
Packaging of Django static files is more complex. This is caused by the semantics of the static files that Django 1.3 introduced (and that can be used in 1.2 installations with the django-staticfiles standalone package).
Historically Django had a concept of media files that a project would have access to. Those media files included both user uploaded (or application generated) content as well as read-only files distributed with each application. With Django 1.3 this changes with the introduction of the staticfiles contrib module. In this model static files are distributed by each application and are finally assembled together to a single directory when the project is configured for runtime. In that model static files are source resources that are built at configuration time and can vary when the administrator reconfigures the application.
The static files of a particular application should be stored in the static directory relative to the application sources. This is in compliance with upstream recommendation.
Packaging Django Projects
Code and Settings
Projects actually have some code although not as much as typical applications do. A the very least each project will have urls and settings. This guide recommends that all project files should be installed to a private python package not to pollute the namespace. The settings should be PACKAGE.settings, the URLS should be PACKAGE.urls where PACKAGE is the name of the Debian package containing the Django project.
This guide does not define how settings should work, several approaches are possible:
- Ship examples and require the administrator to finalize the deployment
- Ship a pre-cooked immutable settings file that looks at configuration file in /etc/PACKAGE/, optionally managed by debconf
Optionally the settings file may be pre-cooked for web server integration so that the administrator can install and use a package immediately without having to configure the web server as a separate step.
Project wide templates are template files that may override any templates shipped with individual applications. This guide recommends that project templates be treated exactly like application templates with two notable differences:
- There should be a symlink to /usr/share/PACKAGE/templates
- There should be an empty directory in /etc/PACKAGE/templates
The configuration file should use both, giving preference to templates defined by the administrator.
Project database settings
Database settings should follow dbconfig-common conventions. In particular if the settings file is pre-cooked for debian and will allow the application to work out of the box then it should integrate with debconf to obtain the appropriate database settings.
TODO: Should the project package depend on PACAKGE-database provided by PACKAGE-mysql PACKAGE-postrgres and PACKAGE-sqlite similarly to the way redmine is packaged today? This would allow to split database dependencies to appropriate sub-packages.
Packaging of manage.py
Packaging of helper programs (such as the venerable manage.py) should follow package-private executables policy. That is, I recommend to store such programs in /usr/lib/PACKAGE where PACKAGE is the name of the Debian package containing the Django project. manage.py should be extended to deal with the private module path and extend sys.path with appropriate pathname ensuring that PACKAGE can be imported properly.
Static Files Cache
Post-install maintainer script should build a catalog of files used by a particular project based on the project configuration. The catalog should be stored in /var/lib/PACKAGE/static where PACKAGE is the name of the Debian package with a Django project. The actual files should be symlinked to relevant media files distributed by each application or project package using manage.py build_static --link for django 1.2 or manage.py collectstatic --link for django 1.3).
The rationale is twofold: First we allow any application to ship any kind of resources needed without having to bother with project configuration, second we allow the administrator to (optionally) change the configuration of the project and add more applications thus triggering the need to reconfigure the static files cache.
Serving Static Files
Static files should be served by a non-django application server (that is, they should never be served by Django directly). This is done for efficiency and security as Django officially discourages this and in fact disables serving of static files through django unless DEBUG development mode is enabled.
This guide recommends that project packages should install relevant web server integration files that would expose the static file cache in an appropriate manner.
Serving Media Files
Media files should be served similarly to the way static files are served, that is, by a dedicated web server and not by the application server. This guide recommends that media files should be stored in /var/lib/PACKAGE/media where PACKAGE is the name of the Debian package with a Django project.
This guide recommends that project packages should install relevant web server integration files that would expose media files in an appropriate manner.
The following questions are open and are a subject of further discussion and analysis. This guide does not attempt to define the best method of doing any of those topics.
- How to expose project settings? (debconf integration / configuration files / python module vs real config file?)
What to do with web server integration? (aka http://localhost/packagename vs do-it-yourself-after-installation, should it just work out of the box?)
- Should the administrator be able to alter the list of applications deployed in a given project.
- Should the administrator be able to override project templates?
Should we attempt to support Django sites technology (http://docs.djangoproject.com/en/dev/ref/contrib/sites/)
Unified support support for south migrations (http://south.aeracode.org/docs/about.html)
- Support for i18n in Django projects (extracting message catalogs, building the packages properly)
A work-in-progress implementation is being written. The code can be obtained with Bazaar from Launchpad. The branch is currently located in lp:~zkrynicki/+junk/django_hello.