Monday, April 30, 2012

Django as a micro framework, including models

The following can be used as a base when you want to avoid the normal structure Django imposes on your project, and you just want everything in a single file.

It is based on similar attempts by Ivan Sagalaev and Fahrzin Hemmati (especially this gist), and a post on stack overflow.

A thing that I consider an improvement over Fahrzin Hemmati's version is that models don't need the explicit app_label and __module__.

# Django as a microframework skeleton, by Allan Boll, 1 May 2012
# Based on
# and

# Settings
appname = 'app'
from django.conf import settings
if not settings.configured:
        DATABASES = {
                'NAME': 'db',
        ROOT_URLCONF = __name__,

# Models
from django.db import models

# Workaround to allow models in current file
import sys
sys.modules[appname+'.'] = sys.modules[__name__]
old_module_name = sys.modules[__name__].__name__
sys.modules[__name__].__name__ = appname+'.'

class SomeModel(models.Model):
    field_name = models.CharField(max_length=10)

# Continuation of workaround to allow models in current file
sys.modules[__name__].__name__ = old_module_name

# Views
from django.shortcuts import render

def index(request):
    out = []
    for obj in SomeModel.objects.all():
    return render(request, 'index.html', {'s': ', '.join(out)})

# URL configuration
from django.conf.urls.defaults import patterns, url, include

urlpatterns = patterns('',
    (r'^$', index),

# Admin site
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin, GroupAdmin
from django.contrib.auth.models import User, Group = admin.AdminSite(), UserAdmin), GroupAdmin)

urlpatterns = patterns('',
    url(r'^admin/', include(
) + urlpatterns

# Running
if __name__=='__main__':
    # Monkey patch get_app to allow models in current file
    get_app_orig = models.get_app
    def get_app(app_label,*a, **kw):
        if app_label==appname:
            return sys.modules[__name__]
        return get_app_orig(app_label, *a, **kw)
    models.get_app = get_app

    # Add models in current file to global list of apps
    models.loading.cache.app_store[type(appname+'.models',(),{'__file__':__file__})] = appname

    from django.core import management