Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#21409 closed Bug (invalid)

Incorrect default BASE_DIR value in project template

Reported by: dmamaev@… Owned by: nobody
Component: Uncategorized Version: 1.6
Severity: Normal Keywords: settings, BASE_DIR
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

It seems to be a mistype:

BASE_DIR = os.path.dirname(os.path.dirname(__file__))

Obviously the BASE_DIR must be an absolute path:

BASE_DIR = os.path.abspath(os.path.dirname(__file__))

Change History (7)

comment:1 by dmamaev@…, 10 years ago

Summary: Incorrect defatult BASE_DIR value in project templateIncorrect default BASE_DIR value in project template

comment:2 by Tim Graham, 10 years ago

__file__ returns an absolute path and dirname is used twice to traverse two directories above the settings.py file. What happens on your system?

comment:3 by dmamaev@…, 10 years ago

os.path.abspath function returns normalized absolute path on different platforms, so it more safely.

For example current defaults with os.path.pardir:

BASE_DIR = os.path.dirname(os.path.dirname(__file__))

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, os.path.pardir, 'db', 'db.sqlite3'),
    }
}

Thensyncdb command starts with these settings it returns OperationalError: unable to open database file on Windows 7 with ActivePython 2.7.2.5, but works perfectly then BASE_DIR is os.path.abspath(os.path.dirname(__file__)).

This solution also works on Debian 7 with Python 2.7.2.

comment:4 by Aymeric Augustin, 10 years ago

Resolution: invalid
Status: newclosed

Thanks for the suggestion. However I believe the current implementation is correct for its intended use case.

If your Django project is stored in a version control system, BASE_DIR should be the root directory. The name BASE_DIR makes it clear that you shouldn't navigate to the parent directory.

If you deviate from the expected repository layout, you should adjust your settings file accordingly.

comment:5 by Dražen Lučanin, 10 years ago

I'm running Ubuntu 13.04 with Python 2.7.5 and am also experiencing problems, because __file__ returns a relative path and my templates are not found as I reported in https://code.djangoproject.com/ticket/21409. The abspath(dirname(__file__)) solution works for me.

This behaviour of __file__ was also discussed in http://stackoverflow.com/questions/7116889/python-file-attribute-absolute-or-relative and http://stackoverflow.com/questions/7783308/os-path-dirname-file-returns-empty.

comment:6 by dev@…, 10 years ago

The double dirname solution works in most cases, but not all - e.g. _ _file_ _ being relative. Also using os.path.dirname on a directory feels unintuitive and anti-semantic.

Unfortunately the right way to do this (from my point of view) is pretty hard to read and complex due to function nesting:

BASE_PATH = os.path.abspath( os.path.normpath( os.path.join( os.path.dirname(__file__), os.path.pardir ) ) )

or shorter:

p = os.path
BASE_PATH = p.abspath( p.normpath( p.join( p.dirname(__file__), p.pardir ) ) )

Maybe we should investigate what people use and how many have problems with this preset.

Regards
Hugo

comment:7 by Harry Percival, 10 years ago

As of Python 3.4, __file__ will always return an absolute path. Could that be an argument for adding the abspath as the innermost call, to make sure that the behaviour in 3.4+ is the same as previous versions?

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

https://docs.python.org/3.4/whatsnew/3.4.html#other-language-changes

Last edited 10 years ago by Harry Percival (previous) (diff)
Note: See TracTickets for help on using tickets.
Back to Top