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.