There is a common knowledge that Django is not suitable for writing small ad-hoc projects that don't need anything special apart from displaying some HTML. Boot-strapping a Django project is considered a work substantial enough to not bother with it just for a couple of functions.

It was always "obvious" to me that it's not the case. But recently, due to some phrase I heard from a colleague, I realized that it's not obvious to everyone. Because many people just don't think about it all the time. Well, you know how it happens… So I'd like to show how to create a Django project with minimal hassle.

Simplification

  1. Don't use the startproject command. It creates a nice project base with an annotated settings file but if it's not your first time looking at Django then you can do without it.

  2. The manage.py file is also not needed since it's just a local "helper" for django-admin.py.

  3. Don't consider the project a container for applications and don't write your code as a pluggable application. Applications are one of the most powerful architectural features of Django but for small tasks you just won't need all this flexibility.

After that we'll have something like this:

This is a fully functional Django project. You can run it with this command:

django-admin.py --settings=settings runserver

What you get is a Django request-response pipeline, template system. Most nice things like form library should also work though I didn't check. What you lose is the ORM and all applications depending on it. But hey, it's for a "micro" task after all!

Extreme

I wanted to push the idea a bit further to see the moment when it becomes absurd and decided to put everything into one runnable module. And I succeeded:

You can run the file like this:

python web.py runserver

However putting it into one file didn't yield much profit. For the file to be readable it has to be separated into named sections. This kind of hints that they really should be separate files after all. Plus, I wouldn't dare to write all this code from memory because of all the boilerplate in it: remember to avoid double initialization of settings, remember long imports etc.

But still it's funny that it worked out :-).

Afterthought

When messing with project initialization I've noticed that ROOT_URLCONF setting is used inside the core of request processing. This binds Django pipeline to the existence of a real module with the defined urlpatterns variable. I think Django would be more flexible if it was possible to set URL configuration programmatically with a simple list:

settings.configure(
    DEBUG = True,
    urlconf = [
        (r'^$', index),
    ],
)

It might be even useful in practice in cases where you need to setup an environment on the fly. In tests for example.

Comments: 16

  1. Google user

    I have a feeling there should be a comma: "In tests, for example".

  2. sh4d0w

    Very cool, I hadn't realized django could be so compact. Coming from a rails standpoint, this reduces the number of files I'd expect in a micro-project by a ridiculous amount

  3. ashish.gd@gmail.com

    This seems super cool and pretty much exactly something I was looking out for. As a novice beginner in Python and learning Django, I often wondered about the heavy boot-strapping Django did for small learning projects. This definitely helps my concern. Though, am still grasping many of the entities used in this post. It would be great help if you could wrap all this in a script and create a utility out of it for someone like me. Many thanks again for this post and explanation.

  4. Eli Bendersky

    Thanks for showing this. I always had trouble understanding what Micro-frameworks are for if everything is doable with a stripped Django.

  5. Luka Zakrajsek

    You can use models too.

    from django.conf import settings
    
    settings.configure(
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.sqlite3',
                'NAME': 'dev.db',
            }
        }
    )
    
    from django.db import models
    import sys
    
    sys.modules['web.web'] = sys.modules[__name__]
    sys.modules[__name__].__name__ = 'web.web'
    
    class MyModel(models.Model):
        name = models.CharField(max_length=255)
    
  6. Good

    Ah! long needed. Many thanks

  7. softwaremaniacs.org - Today, 7:21 PM

  8. What you get is a Django request-response pipeline, template system. Most nice things like form library should also work though I didn't check. What you lose is the ORM and all applications depending on it. Software Maniacs blog » Django as a micro-framework

  9. Andrew Pendleton

    Just for fun, I decided to see how easy it would be to factor what was left of the boilerplate in your single-file example into its own reusable chunk. It turned out to be pretty straightforward, and yielded something like this:

    import djmicro
    djmicro.configure()
    
    from django.shortcuts import render
    
    @djmicro.route(r'^$')
    def hello(request):
        return render(request, 'index.html', {})
    
    @djmicro.route(r'^test/(\d+)/$')
    def test(request, id):
        return render(request, 'test.html', {'id': id})
    
    if __name__ == '__main__':
        djmicro.run()
    

    The source of the reusable chunk is here.

  10. Ivan Sagalaev

    Andrew, this is totally cool! May be it's even getting close to be actually useful :-).

  11. Andrew Pendleton

    Yeah... I'm curious to see if it's possible to encapsulate the application state in an object, like Flask does, rather than having everything be global and having to hang all sorts of stuff like urlpatterns off of the main file. I think Simon Willison experimented with some of this a couple of years ago, so I might look into how he did it. I think getting models working would also be pretty cool (and I see that there are some tips on that in Luka's comment), because I don't think it would be that big of a stretch to be able to build single-file projects that leverage existing reusable apps, like the admin.

  12. В комментариях к посту Django as a Micro-Framework в блоге Ивана Сагалаева некий Andrew Pendleton выложил отличное решение для использования Джанго для микропроектов — djmicro.

  13. Josh

    Nice post. I wish I could speak another language as well as you appear to speak English!

  14. ricky.clarkson@gmail.com

    Some of this seems out of date, e.g., at least in Ubuntu it's now just django-admin instead of django-admin.py, and the 3-file version doesn't run out of the box (apologies, I saw the problem on someone else's machine and don't have the errors to hand).

    It'd be great if you could fix it up somehow for the next gullible fool who says "just search for 'minimal django example' and run what you see"

  15. Ivan Sagalaev

    This post is more than three years old, of course it's out of date :-)

  16. garej

    oh, amazing! what a long time ago this was obvious for some clever people :)))

    @Luka Zakrajsek suggested model connection. A little less hacky solution could be as follows:

    settings.configure(
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': 'dev.db',
        }
    },
    
    INSTALLED_APPS=[__name__, ]       # added
    
    )
    
    from django.db import models
    
    class MyModel(models.Model):
        name = models.CharField(max_length=255)
    
        class Meta:
            db_table = 'table_name'   # added
    

Add comment