Opened 11 years ago

Closed 11 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@…, 11 years ago

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

comment:2 by Tim Graham, 11 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@…, 11 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, 11 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, 11 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@…, 11 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

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