Chicken Scratches

Eddie’s Django Tip #3: Don’t Mix Your Media

Don’t mix user-uploaded content with site-specific content with Django admin content.

This is a simple one, but I have seen projects where this was not followed, and the result was a real mess. so please, please, please do not mix your media!

There are (at least) three types of content that we can think of as “media” in a Django project: There is the Django admin media – the CSS files, images, and JavaScript that come with Django itself for use in the admin interface. Then there is your own static media that you use to style your site. And finally, there is user-uploaded content – things like profile pictures and so on. I recently took over a project where all three were in the same directory. I nearly wept.

In case it’s not obvious:

  • Django media stays with Django. Wherever you have Django installed, be it as a Python Egg, checked out from Subversion, or as part of your OS’s packaging system, keep it there. Use your web server’s configuration to map a URL to that path (taking appropriate security measures, of course). And set the ADMIN_MEDIA_PREFIX setting.

  • Your static media belongs in version control, probably with the rest of your source code. Depending on your work flow, you may want a separate system for the raw Photoshop or Gimp image files and the final web-ready images. I have an /img-src/ directory and a /static/images/ directory in every project, for example. The important thing is that they are separate from other media types, version controlled, and updated when the rest of the code is updated. Important note: Do not use Django’s MEDIA_ROOT and MEDIA_URL settings for this. These settings are for user-uploaded content. Django’s documentation is a little unclear on this point.

  • User-uploaded content stays separate. As always, use caution in what you let your users upload to your server. Validate the files if possible. Create your own file names; that is, don’t let the uploading user choose the server-side name of the file. Limit the upload size. And of course I don’t need to tell you not to run your FastCGI process as root, right? Right? (Believe it or not, the project I recently took over was set up like that, so I guess I do need to say it.)

Just as in real life, it’s important to pay attention to where you put stuff. A place for every file, and every file in its place.

Track comments by RSS

2 responses to “Eddie’s Django Tip #3: Don’t Mix Your Media”

  1. Kurt says:

    I didn’t know that MEDIA_URL was not for static media. What I do is just have an uploads directory inside of my media directory. Is that bad practice? What’s the difference?

    One thing I’ve struggled with on my learning of django, is all the examples seem to assume that they’re the only project running on the webserver, and therefore a the root url. What is the proper way to reference your static files if not via MEDIA_URL? In an app portable fashion?


  2. Kurt, I would not recommend having an uploads directory inside of the media directory. It’s too easy to end up with problems involving a non-version-controlled directory inside of a version-controlled directory.

    * You’ll want to have a backup policy for the user-provided content that is not necessarily the same as your source code.

    * It can be useful to set up specific disk quotas for that data.

    * You may accidentally check in user-provided content into version control.

    * While updating your source code, you may accidentally wipe out the user-uploaded data.

    Obviously, every site is individual and you will want to come up with your own policy, but I have just run into too many issues mixing media, that I believe it’s a good blanket policy to just avoid it.

    Django 1.3 now has a specific module for handling static files: django.contrib.staticfiles