15 ms·
Things I Wish I Had Known About Django Development Before Starting My Company
- bryanh 14y agoWatch out for these Celery gotchas: 1. Tracking tasks status in SQL will result in a lot of queries! (Even when using Redis/RabbitMQ as brokers.) 2. Crontab style tasks are great... until they take a long time to complete and Celery kills them. And then you're back to regular crons (and there is nothing wrong with that). 3. Use UTC everywhere! New projects get this by default, but don't make this mistake.
- jdunck 14y agoMy recc after a lot of heavy use is: RabbitMQ for the queue, Redis for the result store. RabbitMQ for the result store is madness.
- misiti3780 14y agowhy not just use redis for both - just curious ?
- jdunck 14y agoRedis does OK as a queue, but not as well as rabbit. For a start, rabbit handles OOM better. It has lower per-message overhead. It has a more flexible queueing model in general so that you can use it for both work queue-y stuff and other queuing needs. It's interesting how often queues seem handy once they are easy to use. Then there's the fact that redis is good for lots of things other than queues, and you'll be tempted to use it for that, and that will crowd the queue use. If you hold a transaction on redis or do a large set intersection or run a lua script, you block everything else, including your fanned-out celery worker pool.
- famousactress 14y agoSolid list! For most of those bullets I definitely had the 'Oh wow, should have done this sooner' moments. I'd add: - use South (right away!) - Class Based Views - (not django specific) use virtualenvs!
- apendleton 14y agoThe article recommends using MongoDB as a primary data store, so South wouldn't be applicable (and that's specifically addressed).
- conesus 14y agoActually, I use South to manage data migrations (as opposed to schema migrations) in MongoDB. That way I can ensure that I've run the same data migrations on all of my dev and prod databases. Just a `./manage.py migrate` and every developer is caught up.
- mrtron 14y agoAm I the only one left who finds south more trouble than it is worth?
- misiti3780 14y agoi think it is the best solution out there right now ... someone had a kickstarter recently to replace it, but I can't seem to find that info via google right now ...
- briancurtin 14y agoI believe you're thinking of Andrew Godwin's schema migration kickstarter: http://www.kickstarter.com/projects/andrewgodwin/schema-migrations-for-django http://www.kickstarter.com/projects/andrewgodwin/schema-migr...
- misiti3780 14y ago
- apendleton 14y ago> Use Gunicorn instead of Apache for your webserver This is strange advice; while you can use gunicorn as a front-facing webserver, the gunicorn docs strongly recommend against doing so. In a typical deployment scenario, then, gunicorn and Apache would occupy different levels of your stack, with one running your WSGI app and the other exposing it to the world. The advice ought probably to be "Use gunicorn+nginx instead of Apache+mod_wsgi," and indeed, lots of people do make that recommendation about Django deployment.
- misiti3780 14y agosorry - i did forget to mention nginx should be in front of everything managing all requests + serving static content.
- misiti3780 14y agoupdated article
- antihero 14y agonginx+uWSGI emperor mode is such a nice setup.
- tinco 14y agoDid you ever try using Passenger (nginx) to run your WSGI app instead of Gunicorn+nginx? Seems like it would be even less of a hassle to run. (I work at Phusion, and am not a Django guy, just curious)
- misiti3780 14y agoif this question was for the author, my answer is no.
- falsedan 14y ago1. package your python code as a sdist (except setuptools is too hairy so nevermind), keep your deployment scripts & configs in a separate repo or orphan branch 3. use nginx to reverse-proxy WSGI to Gunicorn over a unix socket 6. don't have per-environment config in your app, use the same config in all environments and configure each host with aliases/proxies to consume the appropriate resources (use local_settings.py for local development on your workstation & exclude it from your package) 7. use native operating system service management (systemd, upstart, launchd) 10. use munin if your app can withstand a CPU spike every 5 minutes, use ganglia/graphite/collectd otherwise
- glenjamin 14y agoI have to disagree strongly with your point 6. I'm working on a large app at the moment where all hostnames are the same regardless of environment, and the only way to switch envs is via a proxy. It's a massive pain. Keep environments mostly similar, but always make sure you can configure locations of the app itself and its various external resources separately on staging, test and development platforms.
- falsedan 14y ago> I'm working on a large app at the moment where all hostnames are the same regardless of environment, and the only way to switch envs is via a proxy. It's a massive pain. One of our projects works like this, it sucks. For per-host app location, we set X-HTTP-Script-Name in the nginx location block and extracted it in WSGI middleware like http://flask.pocoo.org/snippets/35/ http://flask.pocoo.org/snippets/35/ Everything else is hardcoded to use 'http://localhost/service_name/foo http://localhost/service_name/foo & nginx proxies to the appropriate resource. Obviously, this doesn't work for non-HTTP services!
- hcarvalhoalves 14y ago> 1. package your python code as a sdist (except setuptools is too hairy so nevermind), keep your deployment scripts & configs in a separate repo or orphan branch This. I'm tired of Django projects not being packaged/released correctly, and deploy scripts that simply git clone in production (yiikes).
- deleted 14y ago[deleted]
- taude 14y agoI like the ideas on directory structure. I've been working in Flask and I spent way too much time thinking about my directory structure.
- Luyt 14y agoYou're also using Flask? I wrote a short piece about roughly the same subject as the author of the original article uses for Django. Running Flask behind gunicorn and nginx, monitored by supervisord: http://www.michielovertoom.com/freebsd/flask-gunicorn-nginx-supervisord/ http://www.michielovertoom.com/freebsd/flask-gunicorn-nginx-...
- taude 14y agoYes, using Flask. I need to write why we chose it over Django....but mostly becasue we're using Mongo and once you're down the path of not using the Django ORM, what's the point? Also, it seems like there's dozens of articles on "how to structure" your large Django projects, so you don't even get good guidance about it out of the box. I'm running mine under NGINX->uWSGI....but might be switching to Gunicorn. (I'm still researching our path to production).
- spamizbad 14y ago> 10gen has added the aggregation framework, full-text search, collection-level locking, etc. Mongo has collection-level locking? I thought there was some preliminary work to support it in 2.2 (It just does database-level locking for now), but it's still unsupported. Source: https://jira.mongodb.org/browse/SERVER-1240 https://jira.mongodb.org/browse/SERVER-1240 Also, I wouldn't recommend using any of the aggregation stuff unless its for infrequent ad-hoc stuff or scheduled tasks during slow periods.
- conesus 14y agoI use aggregation queries regularly and it's amazing. My MongoDB database has 4k ops/sec and I run an aggregation query to count averages, sums, and splits on a name (to get averages and sums for each of two dozen groups) for about 10K rows every 5 minutes. Not a huge amount, but this is on a db that is performing a ton of work. Also, I should mention that you should probably run your aggregation queries on your secondaries.
- misiti3780 14y agoi agree - the aggregation framework seems solid - much better performance than map-reduce
- pvnick 14y agoYou're right, it doesn't yet support collection-level locking (https://jira.mongodb.org/browse/SERVER-1240 https://jira.mongodb.org/browse/SERVER-1240).
- dangoldin 14y agoAn item I'd like to add to Python development in general is to use virtualenv. If you're doing multiple Django projects this is a must have. One of those tools that you start off thinking isn't useful but quickly turns into a must have.
- dshap 14y agoI haven't used Jammit before, but I highly recommend checking out django-pipeline for the same purpose: https://github.com/cyberdelia/django-pipeline https://github.com/cyberdelia/django-pipeline
- Bockit 14y agoSpecifically for me, pipeline fits into django's collectstatic way of doing things. And because of this it works fantastically with django-storages as well. My projects are set up so that `python manage.py collectstatic` trawls all my apps static folders, compiles everything if required (r.js, sass) and uploads any changes to an S3 bucket. And in development it compiles over the wire (except r.js, we let requirejs do the async loading thing in development).
- dshap 14y agoDitto regarding everything up until your last sentence - it is a pretty great setup. What do you mean it "compiles over the wire" in development? In development, pipeline just renders individual js/css tags for each of your static files, un-compiled...
- Bockit 14y agoThat when we're developing, you edit a sass file, and when you request the CSS file it compiles the SASS to CSS before serving the file. It has been a little while since I set it all up but I think for the SASS example I've made a gist[1] showing the settings you need to make it work. If I recall correctly the key bit is using the .scss as the source file. Then, in production make sure to set `PIPELINE = True` to stop compiling per request. [1]: https://gist.github.com/Bockit/5408958 https://gist.github.com/Bockit/5408958
- dshap 14y agoGotcha
- coolsunglasses 14y agoDon't use celery use: https://github.com/binarydud/pyres https://github.com/binarydud/pyres
- mcintyre1994 14y agoI've been expecting to use Celery in a project I'm working on, could you explain why?
- coolsunglasses 14y agoCelery is a PITA and over-complicated for the problem it solves.
- rozap 14y agoDo you know why pyres relies on itty? Seems like kind of an odd dependency...
- lost-theory 14y agoThe pyres web interface (where you can view job status) is built using itty. edit: looks like they're using flask now, I don't see itty being used anywhere. They also split the web interface (resweb) into a separate project, so pyres doesn't depend on a web framework now.
- rozap 14y agoAh ok, thanks. I guess the documentation is a little outdated then. Thanks for the suggestion, I'll check pyres out when I get to that point in my project.
- hobb0001 14y agoCelery is brittle. If you stop a celery service, odds are, it will either not stop at all or leave stray child processes running. It is not transactional, at least not with a MongoDB back-end. If you stop a celery service, any tasks that were in progress may or may not complete, but none of them will be picked up again when you resume. No prioritization of queues or tasks. It is possible to set up separate services that handle different queues, but that's a PITA and there's still no guaranteed order of processing.
- fduran 14y agonginx with uwsgi is also an excellent alternative imho
- pindi 14y ago> Django does not have a built in JSON HTTP response, so you are going to have to either man up and roll your own (good luck) Am I missing something? What's wrong with: return HttpResponse(json.dumps(data), mimetype='application/json') Wrap it up in a convenience function and you're done. The JSONResponse class suggested automatically implements JSONP, which is extremely dangerous. Consider a view on /accounts/info which returns some information about the currently logged in user. A malicious site could embed <script src="http://example.com/accounts/info?callback=someFunction"> and access the account information of any user logged into your site. JSONP is a technique to bypass the same-origin policy in appropriate cases; don't just blindly apply it everywhere or you're giving up the protection of the policy.
- the_cat_kittles 14y agomight also be worth noting that django-tastypie is the defacto standard for REST apis, and sends and returns json (among many other serialization formats) very easily. This obviously doesn't work for all ajax cases, but its extremely useful nonetheless.
- scott_w 14y agoI would recommend Django Rest Framework. It gives you more fine grained control. We just use the serialisers for example.
- lifeisstillgood 14y agoI would guess complex objects - containers, or strange databasey stuff. The way to deal with is __complex__ as a method on the object and recurse through asking the complex method to return nested simpler python types.
- streblo 14y ago12. Use `pip freeze` to keep a list of your requirements, and keep that requirements list in your repo. Use virtualenv and virtualenvwrapper to keep your environment clean from other environments. Virtualenvburrito (https://github.com/brainsik/virtualenv-burrito https://github.com/brainsik/virtualenv-burrito) will help you set it all up. 13. You almost never need to write bash scripts. Use django management commands to write scripts that interact with your application. Use fabric and a fabfile to do deploys. Use something like chef or puppet to do machine configuration. Your bin/ folder will turn into an unmaintainable mess very quickly. 14. Use south. Yes, it's obtuse, but it gets the job done. 15. Use a pre_save hook on all of your models to do full_clean for validation before anything goes to the database. This will save you from cleaning up your data later. from django.db.models.signals import pre_save def validate_model(sender, **kwargs): if 'raw' in kwargs and not kwargs['raw']: kwargs['instance'].full_clean() pre_save.connect(validate_model, dispatch_uid='validate_models') 16. If you're writing a javascript-heavy application, consider all of your options for static asset management before you get too deep. I've used django-compressor, django-pipeline, webassets, and django-gears. None of them are perfect solutions (there still isn't a sprockets-esque one-catch-all solution for django like in the rails world), so consider the pros and cons before you make a choice. edited for formatting
- deleted 14y ago[deleted]
- Bockit 14y agoWould you mind expanding on the issues you have with pipeline? I use pipeline at the moment and beyond a couple of small things (mainly working with vendor apps) I'm really happy with it, but I'm open to the idea that it's because of what I don't know than because it solves every problem.
- streblo 14y agoMostly with setup and configuration. Configuring it to work the way I expected required a lot of digging through documentation/code/blogs/fudging around. I don't like it when I have to do that, for a number of reasons -- a. I'm lazy and I don't like spending a lot of time doing upfront configuration, b. when something doesn't come with sensible defaults pre-configured, I assume I'll do something wrong and it'll have non-obvious but bad consequences. I had this problem with django-compressor as well (but more with configuring 3rd party asset compilation). I usually recommend people use webassets via django-assets. It's easy to configure and very feature-ful.
- overshard 14y agoI had to double check the title because I thought he said Django and all the advice seemed to match my Rails experience and not my Django one, also, this may be a bit nitpicky, but Django isn't really an MVC Framework nor is it a CMS. You can only really call it a web framework as it has elements of these items but isn't the same: 1. The right directory structure, the default use for the media folder is supposed to be using for stuff uploaded through your app, not the files you develop, your static files should go in static and your compressed files should go in media as they are dynamically generated or in your global "static" folder that is pointed to from your web server. You should also have different settings.py files on a per-situation basis. Your development servers, staging, and production environments will probably all have different settings because at the very least development will have `DEBUG = True` and production `DEBUG = False`. 2. This is fine even though it seems wonky to use it for cron jobs to me. 3. This is fine too but I personally use nginx+uwsgi w/ emperor mode. 4. Up to you on this one, there are some nice Django branches that support key-value store databases but don't use the standard Django with key-value databases because it is 100% built around RDBMS. 5. Only piece of advice I agree with completely. 6. As partially discussed in #1 by me. I don't like his override method. I think an import of a base settings into production.py and development.py is cleaner. 7. Supervisor is good here but also if you use uwsgi in emperor mode instead of the suggested gunicorn it can handle the same task saving you an extra install and configuration. 8. Django very clearly has a nice Mixin for JSON responses in the docs or you can build a nice easy API using Tastypie: https://docs.djangoproject.com/en/1.5/topics/class-based-views/mixins/#more-than-just-html https://docs.djangoproject.com/en/1.5/topics/class-based-vie... 9. It's up to you if you want to use Redis, I don't personally need it for all the suggested things and I like how well memcached works with Django out of the box for caching. 10. Munin is great! I'm often too lazy to set it up and am fine reading log files. 11. This drove me to write this long comment... I actually get really annoyed when people try to mix in items from other stacks when there are many solid solutions already that don't force you to install another entire stack. Django has django_compressor which works great in this situation (https://github.com/jezdez/django_compressor https://github.com/jezdez/django_compressor) and a quick Google search will find many other similar solutions that won't require you to install Ruby to work with your Python web app. Source: 6 years of developing Django apps and doing everything that was suggested here and more.
- the_cat_kittles 14y agousing a settings module, requirements directory and environmental variables makes alot of sense (outlined in two scoops of django at https://django.2scoops.org/ https://django.2scoops.org/, a good book)
- metaphorm 14y agoyour django app doesn't look like a django app. the basic premise of the django defaults is that app modules are pluggable and self-contained. all of the static assets, templates, model code, view code, migration files, management commands, etc. related to a particular app should go in that app's folder (which is treated as a Python module with its own __init__.py file). conventionally the app's folder is a first child descendant of the top level project directory (i.e. its in the same directory as manage.py)
- taylorfausak 14y agoThat's true about Django apps, but this post doesn't describe a Django app. It describes a Django project.
- mhahn 14y agosolid list, I would also add that it is extremely useful (I would argue necessary) to use vagrant (http://www.vagrantup.com/ http://www.vagrantup.com/) to manage your development environment.
- misiti3780 14y agothis is actually on my todo list, i saw this video by zac holman a while back: http://zachholman.com/screencast/vagranception/ http://zachholman.com/screencast/vagranception/ and have been meaning to mess around with it ever since
- Pxtl 14y agoThat is an impressively long lost of tools to pick up and get running professionally on top of being a web newbie. Hat tip to that man.
- misiti3780 14y ago~ 2 years and a lot of pinot noir ....
- derengel 14y agoIs mongodb a good choice for CRUD apps also?
- jaegerpicker 14y agodepends on the actual app use. Simple in and out low traffic crud? It's probably not worth the extra effort. MySQL is still a great product that has and will continue to serve billions of web requests and just cause NoSQL is a new kid on the block doesn't mean that everything should use it. That said if you are storing data that is really just documents, Mongo or another document db is likely a good choice. For example if you storing interrelated performance measurements (like in a factory setting ) Mongo would likely not be the best choice but say in a setting like an app for applying for a job or registering for events ( natural document data segments ) a document db would work well for modeling the domain I'd think.
- scrambam 14y agoMongoDB pretends to be good but it isn't. CRUD often means transactions, and my last company went broke because MongoDB doesn't do transactions. Relying on the code to track that crap meant we put our faith in the wrong system. If you want to do anything financial, stick to a database that allows for transactions. This is why BitPay and all the other MongoDB bitcoin sites are going to fail, cause they rely on the wrong tools.
- neo2001 14y agoIt really depends on the nature of you application, but raw speaking... probably you'll regret using mongodb as your primary database at some point.
- tuxidomasx 14y agoThis list is somewhat dependent on the size and complexity of the project. For a small or simple project, many of these points might not matter. For example, if Apache can handle your traffic just fine, why spend time replacing it with gunicorn? Or if you never really migrate your database ever, why waste time fiddling with South? Just a gentle reminder to take into consideration the present and future needs of your project to avoid needlessly adding complexity to it.
- jvm 14y agoI think he's actually saying gunicorn was simpler than Apache. I've also found that to be true (anecdotaly).
- deepakprakash 14y agoThis is indeed a solid list. The most comprehensive best-practices resource of Django I've come across by far is "Two Scoops of Django"[1] by "pydanny"[2]. Its absolutely worth the $17. [1]: https://django.2scoops.org/ https://django.2scoops.org/ [2]: http://pydanny.com/ http://pydanny.com/
- scrambam 14y agoBest book ever! I asked the authors for a free copy because I was broke. I read it, then answered everything right at a job interview. Got the job and finally bought a real copy.
- pydanny 14y agoCorrection: It's not by "pydanny", it's by "pydanny" and "audreyr". She just doesn't do the whole Twitter/HN/blog thing as much as me. Seriously, do you think I could write a section including code that discusses "the impossible condition of too much chocolate". ;-) Seriously, between the two of us she's the better coder, taught me LaTeX, and knows Strunk and White. I just write what I think and let the grammar experts fix it. :P
- shavenwarthog2 14y agoSeconded. My investment in "Two Scoops of Django" has repaid itself many, many times over. Concrete "best practices" book.
- scottrb 14y agoMy supreme thanks to the author for writing this and to all those who have submitted additional items to the list in the comments here. I'm writing my first few Django apps in series and have found this bits of advice to be very valuable.
- falcolas 14y agoI don't see a monitoring system there? Something like Supervisor is great, but who watches the watcher? I prefer Nagios, but that's just because I'm used to it. Even it is better than nothing. If you want something a bit more distributed (read less prone to single points of failure) than Supervisor, check out pacemaker. Very powerful and useful for keeping resources alive in any sized cluster.
- dhaivatpandya 14y agoI wish there was something like this for rails - well written, concise and keeps the newbies away from things that'll hurt them. In particular, some major pain points: 1. Use rbenv or rvm. Half the problems I notice with beginners stem from installing rails with apt-get or something. 2. Your controller is meant to be simple glue between model and view - if you're putting tons of code in there, you're doing it wrong. 3. Unit test. A lot. This is especially good for beginners because you often make little errors when you're starting out. 4. Unit testing isn't enough. Functional testing is important too. 5. Learn about your hosting provider. Specific to Heroku, if you're on the free plan, every dyno spin-up takes absolutely forever if you don't have a steady stream of visitors.
- wikiburner 14y agoI'm somewhat new to Django, and I'm just curious if Heroku is the best solution out there for Django? I've heard some good things about Gondor, and apparently it's more tailored for Django apps, but I'd be curious to know what the HN consensus is on Django hosting that won't collapse on you if you get HNed/Reddited.
- jordanmessina 14y ago> 2. Your controller is meant to be simple glue between model and view - if you're putting tons of code in there, you're doing it wrong. Yes, fat models are the way to go. This is just a good rule of thumb for any MVC framework. I feel like no framework docs actually explain this. Newbies end up shooting themselves in the foot because they don't understand the reason for separation or understand where logic should be implemented.
- mercurial 14y agoThat's very debatable, and pretty rails-specific, IMHO. Conventional wisdom in other ecosystems is instead to have a business logic layer between your controller and your persistence layer. I've always found this to be good advice, as it makes the code more testable and makes reasoning about manipulating different models in the same operation easier.
- Camillo 14y agoThe main thing I wish I had known is that the ORM is rather limited (or, at any rate, it was too limited for my app), and while you can use raw SQL, it won't let you get model objects out of your own queries, which makes it impossible to integrate with the rest of your app that uses the ORM [1]. The first thing I'd do if I had to use Django again would be to eschew its ORM and use SQLAlchemy instead. [1] This was a few versions of Django ago; if they fixed this since then, I welcome corrections.
- SoftwareMaven 14y agoI decided to dive into bootstrap.py/buildout for my current project. So far, it has done a reasonable job of keeping the directory structure clean as well as keeping dependencies under control. The nice thing is that there are recipes for most important things, and adding other new recipes (oh, I need to install and have access to coffeescript) are very straightforward. I see it as a build step before fabric or puppet would take the output and deploy it.
- crucialfelix 14y agoI've used buildout for years but I'm now moving away from it. I've enjoyed it though, and I wouldn't recommend against it. Several issues: the buildout process is long and monolithic and not conducive to minor adjustments. I'm using ansible now and its much better for just changing one setting on an nginx config file or settings file and reloading. I chatted with the author of buildout and he said he was building to an rpm and then mounting that as his means to do a live deploy. I often wished I had virtualenv, so many things work well with it. for instance python-vim and sublime lint / rope like to have a virtualenv to get the python paths. also ctags is happier if I can just enter the virtualenv and run it. there may be a recipe for that but I never found one that worked nicely.
- kitanata 14y agoI'm not sure why this article suggests that you should use jammit when a very nice django specific implementation does the same thing. If you are using django do yourself a favor and skip jammit in favor of django-compressor here: https://github.com/jezdez/django_compressor https://github.com/jezdez/django_compressor If you want haml templates in 1.3 or 1.4 use my fork of djaml here: https://github.com/kitanata/django_haml https://github.com/kitanata/django_haml For all the other asset specific stuff use node packages like less and coffeescript. There is no need to include any rails or ruby code in with your django projects. Good alternatives exist.
- tracker1 14y agoJust want to point out that MongoDB doesn't have full text search perse, but it can do nested array indexes... If you want stubbing/phoneticization you need to do it as part of your input, and part of your search logic... if you front your queries with a service then it is easy enough to do.
- mathias_10gen 14y agoActually, as of 2.4 there is an experimental text search feature built-in: http://docs.mongodb.org/manual/core/text-search/ http://docs.mongodb.org/manual/core/text-search/. While it is no Lucene (and is still considered experimental) it does provide simple tokenizing, stop-words and stemming.
- schrijver 14y agooff-topic, this _Medium_ platform seems to mangle all outgoing urls…
- nnq 14y ago> Use Gunicorn instead of Apache for your webserver [...] This assumes NGINX is managing all incoming requests and serving static content. Why not just go nginx + django the usgi way? Now you have friendly tutorials and docs for this like https://uwsgi.readthedocs.org/en/latest/tutorials/Django_and_nginx.html https://uwsgi.readthedocs.org/en/latest/tutorials/Django_and... . Maybe I'm weird or I've never worked on large enough apps, but I fail to get what the shiny unicorn and gunicorn bring useful tot the table...
- edanm 14y agoThing #1 for me, by a long shot: Deploy to Heroku (or similar). Saves a ton of headaches, saves boatloads of time/money, and for most startups in the early stages, is well worth the tradeoff.
- unwind 14y agoWhy does this page break "space" for paging down (in Firefox 20.0.1, Windows 7)?
- boerni1234 14y ago"Use named URLs, reverse, and the url template tag": For Javascript URL handling use sth. like that https://github.com/version2/django-js-reverse https://github.com/version2/django-js-reverse
- smogzer 14y agoReplace all comments with: Use web2py instead of django
- domrdy 14y agoI tried various asset management tools but prefer having grunt manage all frontend related things. Node projects seem to be better tailored for this. Especially stuff like linting and watching for code changes, plus having a js based config file for people that don't speak python.
- Judson 14y agoThis may sound strange, but when I first started doing python stuff with Django, I spent WAY too long trying to figure out the best project directory layout. To me, Django should generate a "pretty-good" directory layout, much like `rails new`.