On Mon, Dec 10, 2012 at 8:59 PM, Lachlan Musicman <data...@gmail.com> wrote:

> Hola,
>
> I've got a split settings set up for my prod/dev sites, and in all the
> hints I've  seen over the years, I've most appreciated the line at the
> top of the settings file that goes like this (there are variations to
> the theme):
>
> BASE_DIR = os.path.dirname(os.path.abspath(__file__))
>
> But almost all of the docs that I grab this info from are pre
> Django1.4, and I believe it was 1.4 where the structure changed
> slightly - settings are now in
>
> path/proj/proj/settings.py
> path/proj/app1
> path/proj/app2
>
> I would like BASE_DIR to be path/proj/ so I can use it in
> STATICFILES_DIRS for instance, but it's coming out as path/proj/proj/
>
> I am thinking about:
>
> SETTINGS_DIR = os.path.dirname(os.path.abspath(__file__))
> BASE_DIR = os.path.join(SETTINGS_DIR, '..')
>
> But it seems a bit convoluted or horrible.
>
> Does anyone have a better solution they could share?
>
> cheers
> L.
>
> First stuff you almost certainly already know, so we're using the same
terminology.  In pre-1.4 it was the directory containing the settings.py
file that had to be on sys.path in order to be able to have custom apps
installed there and to be able to reference them without using the project
name.  (If you weren't going have things imported that way, it didn't have
to be on the path, but this only shows up for mod_wsgi deployments, since
cd'ing to that directory to run a management command like runserver
automatically causes python to add this directory.)  When run from
manage.py, Django did a trick of temporarily adding the parent directory to
sys.path, importing proj.settings, then removing the parent from sys.path.
For this to work, there had to be an __init__.py file in the settings.py
directory (still does), making it a package.  This took advantage of the
fact that once a package is imported, it no longer needs to be on the path
to import its contents, allowing, for example, importing prog.urls among
other things, but without littering your top level namespace with any other
modules or packages that happened to be in the parrent directory.

In 1.4 plus, there is an extra directory level, by default, duplicating the
project name(*), and manage.py is moved up to the higher level, rather than
sharing with settings, urls, etc.  Since this directory is on the path
already (if you cd here and run python manage.py ...), no fiddling with a
temporary add of the parent is needed, nor done.  The upper directory is
not a package, so it doesn't need an __init__.py file.  The proj package,
from which settings, urls, and wsgi can be imported, is just on the path,
so these project name qualified modules load just fine.  If you want apps
that aren't qualified by the project name (so that you can override ones in
site-packages, or so that they are portable), start them in the upper
directory.  If you want some apps that have to be qualified with the
project name, start them in the lower directory.

So we have three interesting pieces of information.  The name of the
project, call it PROJECT_NAME.  The path to the directory containing
manage.py, call it PROJECT_ROOT.  And the path to the directory containing
settings.py, SETTINGS_DIR.

    import os, django
    SETTINGS_DIR = os.path.dirname(os.path.abspath(__file__)
    PROJECT_ROOT, PROJECT_NAME = os.path.split(SETTINGS_DIR)
    if django.VERSION[:2] < (1, 4): PROJECT_ROOT = SETTINGS_DIR

I typically define some functions with short names here, typically _m, _r
and _s, that perform string join with '.' or os.path.join of their
arguments onto PROJECT_NAME, PROJECT_ROOT, and SETTINGS_DIR respectively,
allowing me to say things like:

    ROOT_URLCONF = _m('urls')
    TEMPLATE_DIRS = (_r('templates'),)

etc.  (I actually haven't found a need for _s, and usually don't define it).

[* Note that the name of the upper directory doesn't matter.  You can
rename it, cd back in, and the manage.py commands all still work.  If,
however, you have deployed with, say, mod_wsgi, you will have to tell it's
configuration files about the change.  The approaches above can keep the
project name out of settings.py and wsgi.py so that if you change the
project name itself, you need merely rename the directory, edit manage.py,
and edit any front end proxy configuration that has absolute paths, such as
for mod_wsgi.]

I had put this stuff into a package that I could install in site-packages,
and which had a singleton instance of a class initialized by passing it
your __file__, but never got around to releasing it.

Bill

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to