6

I am new to Django and starting a project, and I would like to do it the right way.

I would like to know what you think is best practice for organizing a project.

Here are some questions I have:

  • How do I separate the static resources from the Python code so that I don't waste time processing the static content through Django?
  • As apps are reusable modules, they are not really tight to a project, so should they be located in the project directory, or in another directory that would contain all my "homemade" apps?
  • Are templates considered to be static or dynamic content?

Here is my current file hierarchy:

webapps/
    myproject/
        apache/
        bin/
        lib/
        templates/
            app1/
            app2/
        src/
            app1/
            app2/
            __init.py
            settings.py
            urls.py
            manage.py
        myproject.wsgi
    admin/
    static/
        css/
        img/

What do you think? What would be better?

Thanks!

nbarraille
  • 9,926
  • 14
  • 65
  • 92

3 Answers3

5

Your directory structure could also depend on what version of django that you're using. If you're using django 1.3, handling static content has changed slightly. Your templates could also be arranged separately.

The following only applies for django 1.3.

Within an app directory:

...
app1/
    static/
        app1/
    templates/
        app1/
    models.py
    ...
    views.py

If you use the new django.contrib.staticfiles application, your settings may look something like this:

MEDIA_ROOT = path.join(ROOT_PATH,'uploaded_media/')
MEDIA_URL = '/uploaded_media/'
# static content is collected here, and served from here, but don't add stuff manually here! add to staticfiles_dirs
STATIC_ROOT = path.join(ROOT_PATH, 'collected_static/')
ADMIN_MEDIA_PREFIX = '/static/admin/'
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (
    path.join(ROOT_PATH, 'src/extra_static/'),
)

STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

Similarly, your templates can be loaded directly from an INSTALLED_APP:

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader'
)

TEMPLATE_DIRS = (
    path.join(ROOT_PATH,'src/templates/'),
)

The two strategies above mean that templates and static content can live within their specific app directories. In Development, using contrib.staticfiles, static content can be served directly from your application folders. In production, there is a management command to collect all the app directory static content to /path/to/project/collected_static/, and you can point your web server at that directory to serve static content.

For pre-packaged libraries, using virtualenv and pip is a great idea. Otherwise, I like to keep libraries in a lib directory within the project root directory. It makes referencing the source, templates, and static content extremely convenient, rather than installing to site-packages (especially when not using virtualenv).

So, re-arranging your project structure:

webapps/
    myproject/
        apache/
        bin/
        lib/
        collected_static/
        uploaded_media/
        myproject.wsgi
        src/
            templates/ # lib template overrides and site wide templates
                base.html
                lib_1/
                    nav.html
            extra_static/
                lib_1/ # libs that dont support django 1.3 static
                    js/
                    css/
            settings.py
            settingslocal.py # keep developer specific settings here
            urls.py
            manage.py
            app1/
                __init.py
                static/
                    app1/
                        js/
                        css/
                templates/
                    app1/
Josh Smeaton
  • 47,939
  • 24
  • 129
  • 164
  • Somewhat unrelated to the original question but related to the use of "/static/" to store your static resources ... I deployed a Django app to a Bitnami Django VM on Amazon Web Services and all client requests for my static resources were returning 404 not found. I eventually traced this to django.conf file which contained the following alias: Alias /static "xxx/python2.7/site-packages/django/contrib/admin/static" So all requests for "/static/xyz" were being aliased away to another location and failed. Just wanted to note this in case anyone runs into the same problem. – jarmod Feb 18 '13 at 18:44
3

My designer doesn't want to go hunting everywhere (all over the python path) for template files. My template layout follows yours in that there is one template folder and all the apps go below that. Each app has its own base.html that extends basebase.html.

Here lately I've started following the pinax model of an apps folder, and all apps go in there. The reason for this is purely aesthetic since Wing shows me a tree, all my apps are clustered together in that part of the tree. What I didn't like was an app that sorted out alphabetically after templates or media or site_media. Scrolling up and down the tree slowed me down. By putting all the apps into one place in the tree, git commit -m "feature notes" apps checkins in the code changes too which is another plus.

webapps/
  myvirtenv/
    bin/
    lib/
    myproject/        <- Source control starts here
      site_media/
        collected_static/
          js/
          css/
          img/
        uploaded_media/
      deploy/
          myproject.wsgi
          procmail scripts
          apache site files  # linked from /etc/apache2/sites-endabled
      apps/
        app1/
          templates/       <- This should be here, but in practice I just leave in templates below
            app1/
        app2/
      templates/ # lib template overrides and site wide templates
        basebase.html      <- I changed the name to help my designer
        app1/
        app2/
      settings.py
      gethostname()_local_settings.py # keep machine specific settings here
      urls.py
      manage.py
      requirements
        base.txt
        project.txt

There were too many base.html files and talking about it was difficult, so basebase.html was born and we've been happy with that ever since.

I haven't had any static files that didn't work with the staticfiles app. I was using that app with 1.2. I haven't gone back and done the 1.3 static folders yet but I probably will in the next few months as things get worked on.

I got the requirements folder trick from pinax.

  1. Create VirtualENV
  2. git clone url
  3. pip install -r requirements\base.txt -r requirements\project.txt
  4. manage syncdb (if using sqlite, otherwise you have to do db creation tasks first)
  5. symlink from /etc/apache2
  6. reload apache config
  7. Profit!
boatcoder
  • 17,525
  • 18
  • 114
  • 178
  • This looks like I can grow into from what I'm doing, but I will keep shoving `myvirtenv` (I just type `venv`) inside `myproject`. Great for clones, but using startproject requires me to create the project using a different (similar) virtualenv, then go into the project and set up my virtualenv. I just ignore `venv` from source control. – sage Dec 25 '13 at 02:06
0

You've had some good thoughts here. My first reaction is to ask what that admin directory is doing? The admin is part of Django, and doesn't need a separate module - and the app-specific admin.py files need to live within their respective apps.

To answer your questions:

  • separating static and dynamic: this is done at the level of your web server configuration. In your case, your apache virtualhost conf needs to have an entry for the webapps/static directory, but not for anything else. The documentation has a good example.

  • If the apps really are completely decoupled from your project, then yes they could live outside it, as long as you put them onto the Pythonpath. One good way is to keep them in separate code repositories, and install them into your project with pip and virtualenv. However, I think you'll find that many of your apps will be project-specific, so live within your project directory.

  • Templates are very definitely dynamic content. If you serve them directly with Apache, they won't be parsed, so your users will see the code for the variable and block codes rather than the values.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895