top | item 6661019

Django plugins you shouldn't start without

170 points| hgezim | 12 years ago |blog.hndigest.com | reply

85 comments

order
[+] aroman|12 years ago|reply
Maybe I'm delusional, but even as someone who has worked pretty extensively (4 months of full stack Django development) with Django, posts like these things make me want to stay away from Django.

I read this post, and I see bandaids. I see bloat, and I see warts. I don't want to build on a codebase that needs 5 extensions out of the box to be sane.

Granted, I know this is not the real story with Django. It is a rather lovely, if rather rigid and stubborn framework (at least it was when I was writing with in circa 1.3). And it is powerful.

But, and this is my point, it seems to me that there is almost no reason I would use Django over something like flask for anything but the most basic of apps. Any time you need to do "serious" work — beyond cookie-cutter stuff — you're going to need to seriously extend Django (or any other web framework for that matter, in my experience/humble opinion). And then it gets ugly, and you're better off building from the ground up on a minimal codebase than trying to contort an existing one to do what you need it to.

Actually, most of my thoughts have been summed up 5 years ago by one of Flikr's lead architects (iirc) at DjangoCon '08 in a brilliant (and hilarious) talk: http://www.youtube.com/watch?v=i6Fr65PFqfk

[+] subway|12 years ago|reply
I don't want to build on a codebase that needs 5 extensions out of the box to be sane.

I want to build on a platform where far more than 5 extensions are needed to be sane -- I want the vast majority of my "core" functionality to be provided by an extension.

Far too often "Batteries included" means "Batteries soldered in with a thick layer of epoxy on top".

[+] tcdent|12 years ago|reply
I've watched the ecosystem from the pre-1.0 days and it is still steadily evolving. New packages are being developed (and abandoned) every day. Some of them are very mature, others are just starting, and many are just plain bad.

Implementations that stand out, like south, may get incorporated. Especially when they're valuable to the core of Django; all may not agree, but migrations (and class based views) should have been in there from the start.

Others depend on your needs. Don't force me into using TinyMCE as a rich text editor, I'll regretfully make that decision myself. I want to choose the best available package for my CDN host. I'm switching thumbnail processing engines because mine hasn't been updated in over two years.

Importing all of my models into the shell is best left as an explicit modification for those that want it. If it was a good idea, why wouldn't Django do it by default?

Reasons to use Django over other, lighter frameworks:

* The ORM

* Forms – The ORM

* contrib.admin

* Authentication

* Extendable command line interface

[+] jdunck|12 years ago|reply
(django core feedback):

Django is not perfect, and will never be. It's now a fairly large codebase, and though there are a bunch of committers, people often feel it's easier to write their own library than push things into core.

Separate from that, some things really don't belong in core - they aren't generally applicable, even if they are valid use cases. We prefer to address minority use cases with extensibility. Rather than saying "your use case is not valid", or saying "give us your kitchen sink", we say: "OK, that's a nice sink - why can't you currently use it? What if we add this valve here?"

In the best (and, I think, fairly common) case, people write libraries, the community finds it generally useful, and the best of that library gets incorporated. We've gained authentication, cache, and migration improvements that way.

There are warts, but the proliferation of libraries are not bloat - they are often a resistance to bloat. Search github for django + jsonfield, and you will see quite a lot of opinions about what it should be. If we'd added the first one that seemed decent, we would have been adding a wart for many people.

I have used all of the recommended libraries before, and while they are nice, I wouldn't call them essential. It works fine without them. Some of the -extensions are very nice, but they rely on 3rd-party libraries, and django has had a pretty conservative dependency policy - python, your database driver, and you're generally ready to go. I think that's a win -- you can add additional dependencies if you want them. Of the libraries, only South is a thing I have used on most projects, and as noted elsewhere in the thread, that's being incorporated into core. As for grappelli - I think the admin needs an update, and we've worked off and on on that quite a bit. Grappelli imagines one direction for improvement, but I don't think it's what core should be -- and I suspect the Grappelli maintainers would agree.

With all that said -- I consider flask roughly comparable to sinatra -- it is smaller, but what parts there are make additional, not fewer assumptions about what you're building. SQLA is a way more powerful ORM than Django's, but I don't often feel limited by Django's. And when I do, there's .raw or .execute. I find SQLA to be overkill for the sorts of queries you'd do in a web request.

If you're saying: you'd rather learn best-of-breed libraries and compose them yourself -- that's a valid point of view, but it's an opinion, not a correct answer for all sites or situations. Since reuse-in-the-large is still an unsolved problem, a thing that falls out of using different libraries and composing yourself is that you lose the community's bounty of components that work with your particular system composition. As for me: I recognize that django is larger and harder to pick up than flask, but I suspect that if you instead (and, IMHO, more properly) compared picking up django with picking up flask, SQLA, jinja, flask-admin, etc -- then they compare favorably in terms of uptake -- and django still gains from the community's many django-* libraries.

[+] bmelton|12 years ago|reply
If it helps any, as someone who's been building Django sites for years, I will say that while all of those are at least handy, absolutely none of them is needed.

On the list, the only one I use with any regularity is South, which I do consider must-have. That said, it seems that the Django core team agrees, as it's being (or maybe is even finished) pulled into Django core.

[+] StavrosK|12 years ago|reply
What, no django-annoying? That's the first thing I ever use:

https://github.com/skorokithakis/django-annoying

That, and shortuuid:

https://pypi.python.org/pypi/shortuuid/

Disclosure: I maintain one and wrote the other, but they and South are the three things I use for every project.

[+] jdunck|12 years ago|reply
django core here, some feedback on -annoying:

It'd be nice if you were clear about what versions of django and python are supported.

From django-annoying's feature list:

    * render_to - seems to be roughly equivalent to django.shortcuts.render
    * signals decorator - now in core[1] (since 1.3)
    * ajax_response - seems useful, though might make sense to check request.is_ajax[2]
    * autostrip - hmm, seems oddly edge case-y, I definitely wouldn't apply it to all my forms
    * get_object_or_None - nifty 
    * AutoOneToOneField - assumes the related model is valid with only the FK filled in, which seems fairly unlikely in many OneToOne cases.  I'm not sure if this was proposed to core, but I'd think it would need some sort of default= fillin feature to be more generally useful.
    * JSONField - soo many competing and variously featureful implementations. This has been discussed a few times; it seems fairly easy to implement and hard to gain consensus. I wish we could get it in core, but the juice doesn't seem worth the squeeze.
    * get_config - I don't think I understand the purpose of this, unless you're just trying to be more intention-revealing than getattr(settings, ...)
    * HttpResponseReload - nifty
    * StaticServer - I don't think I understand why you wouldn't want to config urls.py instead.
[1] https://docs.djangoproject.com/en/dev/topics/signals/#connec...

[2] https://docs.djangoproject.com/en/dev/ref/request-response/#...

[+] jorde|12 years ago|reply
Django-annoying is freaking awesome, I have been using it for couple years now (get_object_or_None and render_to <3). Didn't know that you had taken it over from offline, great job.
[+] bigsassy|12 years ago|reply
Love django-annoying too. It's always got a line in requirements.txt for my Django projects :)
[+] bmelton|12 years ago|reply
ShortUUID looks like fun. I usually just get a UUID4 and grab the last section of the generated UID.

Something like str(uuid.uuid4()).split("-")[4]

I'd like to say that I then do a duplicate check, but I don't think I've ever had a collision, so I'm not actually 100% true that I do.

Best case, you've saved me a database query, worst case, you've saved me a potentially painful Exception.

Danke.

[+] ris|12 years ago|reply
Excellent. Pile up your django with extensions, then look forward to the fun when you have to port your app from e.g. django 1.3 to 1.5 and find a new set of versions of all of your dependencies that work nicely together. And of course figure out a migration path for it all. That is, if extension xyz is still maintained at all.

Lean is beautiful, people. Carefully assess every dependency you add, as each one has the potential to become a burden.

[+] StavrosK|12 years ago|reply
Wait. If you need a piece of functionality, you either get something that works out of the box, or you spend X hours writing it. If the out-of-the-box thing breaks and you spend Y hours fixing it, then Y has to be much greater than X to not be worth it, which, in my experience, it never is.

Not to mention that, if the library broke, then the thing you would have written would have probably broken as well, and you wouldn't have the benefit of a thousand other users who might have had (and fixed) the problem before you. This just smells of FUD to me, as it rarely is a problem to me in practice.

[+] andybak|12 years ago|reply
I've had to handle this multiple times as my Codebase was started on Django 0.96 and currently supports Django 1.6

3rd party libraries upgraded painlessly in 90% of cases aside from those few that had been abandoned. And usually they were abandoned because the community had coalesced around a much better library.

So 3rd party code? Change a line in requirements.txt and bam. My own code? Had to upgrade it manually each time.

[+] spmurrayzzz|12 years ago|reply
I don't think I'd ever feel comfortable starting a Django project of any size without using South. Wish I had known about it since the beginning of my time with Django.

Migration implementations for any platform have always been somewhat vexing for me, but South has been all but automatic for me. I've never had to deviate from `schemamigration app --auto && migrate app`.

[+] jsmeaton|12 years ago|reply
I'm in the unfortunate situation where we use Oracle as the backend database on our projects, which South has never really properly supported. I've done without it, and it isn't very nice.

On the other hand, I ensure that every change that needs to be made to the schema can happen at any time, and both new and old versions of the code will happily work. I believe this helps with upgrading in that there is no delay during deployment and migration. Having not used south on a real project though, I'm unsure if this is a false benefit.

[+] damon_c|12 years ago|reply
If you're using or considering using class based views, I have found Django Vanilla Views to be pretty much a pure win. They really make class based views feel so much more natural. I'm not going back.

http://django-vanilla-views.org

[+] robomartin|12 years ago|reply
As someone who is just starting to dive into Django and Python in general I have to admit being confused by benchmark after benchmark that puts Python near to the bottom of the performance curve when compared to other technologies (Go being one that jumps out at me).

I have to admit that part of me is wondering if I am making the right decision in investing time, effort and money getting up to speed on Python/Django for new projects rather than devoting that time to something like Go. Can't do both. Not enough time and we need to get things done.

Now, I do appreciate that Python has a huge ecosystem and lots of very useful libraries out there. That alone might make the price of admission worth it. I also look at these benchmarks and it seems that PHP (something I am really trying to leave behind) frequently scored above the various Python ecosystems.

Can someone put this into perspective for me? In the end performance can and is hugely important. What am I missing when looking at all of this?

[+] patio11|12 years ago|reply
For many web programming tasks, your user-perceptible speed and/or maximum system loads will not be dominated by the performance of your web application but rather by database, I/O (including networking), and client performance (JS performance, aggressive asset caching, CDN usage, etc etc).

Go or Java are wonderful languages if you have serious number-crunching needs or if cutting your server budget in half would save you a billion dollars. My server budget is $500 a month and if you doubled the performance of all of my servers it would be $500 a month. I'll elide the detailed explanation of the whole "User clicks a button" to "User sees something happen" HTTP request waterfall chart but my Rails app is generally less than 5% of it.

YMMV if you're Google, but I'm not Google.

[+] vdaniuk|12 years ago|reply
I am also a novice and not an authority on Python, but can offer three reasons for using Python even if it is not fast as other languages.

1. Raw language speed is an important factor to consider but for some projects language syntax, community, ecosystem and libraries are much more significant. Those are python strong aspects. Due to its simple syntax, Python is very popular at mooc platforms, such as Coursera, edX and Udacity. Really lots of very good educational content and I mean MIT level good.

2. Usually web projects do not need to scale that much. Website traffic distribution follows power law so if you do not expect your project to be in top 1%, Django will usually handle all standard CRUD workloads.

3. There are Python bindings for many C libraries, for example image manipulation with C speeds is available using ImageMagick bindings.

[+] stiaje|12 years ago|reply
Very often in web development, the kind of performance Go or Java delivers just isn't necessary. You'll often find that the time you spend on developing new features is much more important, and with python I think this can be significantly less.
[+] rmrfrmrf|12 years ago|reply
Here's the advice I was given: if you're going to go with an opinionated framework, go with Rails. If you really want to use Python over Ruby, go with Flask. His thought is that Ruby is more dogmatic than Python by design, so Rails' dogmatic nature lends itself to Ruby more. Python's flexibility lends itself to a more flexible, lightweight framework like Flask.
[+] zzzeek|12 years ago|reply
the perspective is, if you can be 20% more productive in Python vs. Go due to the ecosystem and style of Python, you can spend all the money you save in development costs on a few more servers to offset whatever performance penalties you find. I'm not sure what benchmarks you're looking at, but in the real world Python provides the infrastructure for extremely high volume sites like Reddit, Dropbox, Hulu and a crapload more.

That's not to say runtime performance issues have no effect, for example if you had some kind of algorithmic server at the center of a high frequency trading system or something like that, then benchmarks might be more critical (in which case write that one service in Go or C, then have your Python infrastructure talk to it via REST or as a C extension). It kind of depends on what you're doing but in the vast majority of business cases, it's not.

Pypy is also a great alternative to cPython which I hope starts to become viable for widespread production usage very soon - it features performance a lot more like the JVM.

[+] ericd|12 years ago|reply
I'll provide a dissenting opinion from everyone else and say that it's very nice being able to run a large site from a small number of web servers with very snappy requests, and to do this, it helps to not have the framework eat up 100ms. Also, a well tuned database or KV store can be extremely fast - just make sure all data is buffered in RAM and/or on SSDs.

Doing this right saves you from having to go all out on caching, and it can help keep your infrastructure simple, the benefits of which shouldn't be underestimated if you have a small team.

Also, if you're building interactive B2C sites and have some success, server costs can quickly become nontrivial, to the point where a 2-3x speedup can make a large monetary difference, and it's easier to not have to rewrite things for speed. If you're building B2B SAAS sites, server costs are probably a complete nonissue.

[+] tptacek|12 years ago|reply
I adore Golang, but I would not use it to build a database-backed web application, and would look funny at anyone who did. Golang is a painful language to build conventional web apps in. Stick with Django for now.
[+] ingrownpsyche|12 years ago|reply
I wouldn't take random benchmarks on someone's blog particularly seriously. There are many different performance metrics and many different ways to configure your web server and database. Most of the time these things are IO bound in these types of applications. Ultimately it depends on your particular application (which will probably be a little different from "hello world" and so will have a different performance profile). That said, it's not particularly surprising the Go would go faster for most equivalent (the concept of equivalence between programs in different languages is a tricky on itself) programs given it is compiled ahead of time and has complete type information about programs. I would remain a little dubious about the whether the benchmarks involving PHP were really comparing like with like.

My advice is not to sweat it and know that if/when the time comes that there are plenty of options for making things fast such as load balancers, serving static files from another machine, database on a different machine, various kinds of caching (whole page, database level or somewhere in between), tweaking the number of python threads/processes, etc and that you can choose these based on the results of benchmarks. A lot of the time there are big wins to be found in optimising frontend stuff first anyway.

[+] vikp|12 years ago|reply
I think it really centers around ease of use, amount of libraries, and community support. Django is widely adopted, has a long history of use, and is relatively easy to get started with. Performance is obviously important, but there are plenty of major websites using Django, so it can scale. This is a decent thread on that: http://www.quora.com/Django-web-framework/What-is-the-highes... .

Here is a great comparison of Go and Django: http://lincolnloop.com/blog/djangonaut-building-webapp-go-go... .

I personally have used Django for quite a few projects, and haven't had any "I wish I used a different framework/language" moments.

[+] drdaeman|12 years ago|reply
Those benchmarks are for CPU-bound tasks. Typical web sites usually have other kinds of bottlenecks.

So, if you're doing heavy calculations in your user interface layer (that's what a web site is) - you're a) supposedly doing something wrong b) probably better with something else than plain CPython.

In many other cases, Python is fine. Not the very best option, performance-wise, but there are many other aspects than performance, too.

[+] xAmadeuz|12 years ago|reply
I'm certainly no expert, but thought I'd chime in as I have been wrestling with the same issue. I enjoy web development and have done projects with Java with JSP's, a few smaller projects with Rails, a large Django project, and now am playing with Rails again.

Your performance concerns (and I believe the other comments have touched on this) likely don't matter for most real world sites, and then, even if you get big, you can probably work it out (Pintrest is done with Django I believe, Github is rails, etc).

The question you really want to ask yourself is what does your compiler/runtime do for you. I've been pretty much solely a Python developer for the past year or so, but I like Java (... yea, I know), and find Go interesting, too. A compiler is no excuse to not write tests, but you know what you've written is going to run after it compiles. Added datetime's wrong in Python by adding one that has a timezone marked and one that doesn't? Runtime error. In fact, everything is a runtime error. Tests should not be optional regardless of language, but with Python and Ruby, they really take the place of the compiler in statically typed languages.

I don't want to discourage you from Python by any means, the Django community is fantastic, and Rails 4 with it's Russian doll caching seems pretty sweet. And nothing can beat the libraries for these two projects. The other options that I've seen (ASP.NET, Java Play, Go Revel, all for which, admittedly, I've only done preliminary reading about) just don't seem to have the libraries to get you off the ground as fast (though, if you've never written all the tedious stuff like user creation, email password resets, it is a good exercise in web development basics).

If you stick with Python I encourage you to: 1. Tackle learning the best practices for testing as you go. 2. Check out Two Scoops of Django [1] after having used Django for a bit. 3. Learn good server management skills (maybe look into Puppet [2])

The third seemingly is an offshoot, and would be necessary for really any framework, but once you're ready to deploy your app, you'll likely spend a great deal of time comparing your various options for stack choices and will get your sever set up just how you want it. Make sure that process is easily repeatable. If you don't like how Puppet does it, look into Chef or Salt Stack or whatever; these will save you tons of time down the line.

[1] https://django.2scoops.org/ [2] http://docs.puppetlabs.com/mcollective/reference/basic/getti...

[+] goblin89|12 years ago|reply
I respectfully disagree with OP.

I would say that django_extensions is handy enough to have it included (mainly for the sake of shell_plus and runserver_plus), South is invaluable (although migrations are going into the core in near future[0]), but others—it very much depends on the project.

sekizai is one I've never heard about before. Judging from the first sight, I think it can make templating more flexible, but at the cost of increased complexity.

Earlier I thought that reversion is great to have by default, and I was adding it to every project. Then, as I recall, mysterious errors started popping up one day in one project after Django update. They turned out to have something to do with reversion compatibility. I looked into it and found that we had no use cases for reversion—I could simply throw it away without any consequences, which I promptly did.

I've used grappelli for a while, but in the end I found its UI less usable than native Django admin UI. (Recently I stumbled across http://djangosuit.com/ — this one does seem more functional, although I've never used it in my projects yet.)

[0] https://docs.djangoproject.com/en/dev/topics/migrations/

[+] jdunck|12 years ago|reply
If we're just plugging useful packages, I'd suggest these as useful and broadly applicable:

    * django-debug-toolbar
    * django-secure
    * django-celery
    * django_compressor
[+] streeter|12 years ago|reply
FWIW, South won't totally be necessary after Django 1.7. Django 1.7 is getting support for migrations built-in.
[+] monokrome|12 years ago|reply
In context of this article (at least), Sekizai is useless. You've been able to do this out-of-the-box with Django for a very long time. You can always reference inherited content in a Django block with {{ block.super }}. This feature has been around since AT LEAST v1.1. That's when I found the feature.
[+] ojii|12 years ago|reply
author of sekizai here. you seem to misunderstand what sekizai does. it's not a replacement for block.super. it's main points are support for included templates, for loops and being able to put content anywhere in the template from anywhere. It is however entirely possible that you have no use case for it, but dismissing it as useless is a bit harsh in my opinion.

Further reading on why sekizai and what it does in this blog post: http://ojii.ch/post/why-sekizai/

[+] Spiritus|12 years ago|reply
Yes `select email from auth_user;` is hard.
[+] rMBP|12 years ago|reply
Wow, sekizai looks great. Removes many of my headaches with django's limited block system.
[+] michaelmior|12 years ago|reply
{{ block.super }} does the trick for me.
[+] skizm|12 years ago|reply
Why is south not number one in flaming gold letters? Seriously, south should just be part of django at this point and it is insane that there isn't this functionality built in. Is changing your data models after you started development so crazy?
[+] rmc|12 years ago|reply
Database migrations are being added to Django core, by the author of South.
[+] tehwalrus|12 years ago|reply
isn't the South functionality there out of the box in rails? I've only ever written one rails app in my life, and I now use (non-Django) python all the time, but needing a 3rd party library to handle db migrations sounds like madness, and makes me want to re-learn ruby rather than use Django.