{{{
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
}}}
Because there's no abspath, you can get different results for BASE_DIR
depending on how settings.py is run. This is an edge case, since
settings.py is almost always imported by django in the right context, but
still -- compare:
python manage.py shell
>>> from django.conf import settings
print(BASE_DIR)
With:
python -i myproject/settings.py
>>> print(BASE_DIR)
As an aside, in general, in any path wrangling you should always call
abspath first. Try running this script, saved to a file:
import os
print(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
As to tests, the only one I can think of would be a pretty horrible one
involving actually callling out using subprocess.Popen to a python -i of
the project template settings file, so maybe ok not to bother?
credit to @CleanCut for turning me onto this weirdness!
--
Ticket URL: <https://code.djangoproject.com/ticket/23436>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0
Old description:
> ref the default project template's settings.py, BASE_DIR is defined as:
>
> {{{
> BASE_DIR = os.path.dirname(os.path.dirname(__file__))
> }}}
>
> Because there's no abspath, you can get different results for BASE_DIR
> depending on how settings.py is run. This is an edge case, since
> settings.py is almost always imported by django in the right context, but
> still -- compare:
>
> python manage.py shell
> >>> from django.conf import settings
> print(BASE_DIR)
>
> With:
>
> python -i myproject/settings.py
> >>> print(BASE_DIR)
>
> As an aside, in general, in any path wrangling you should always call
> abspath first. Try running this script, saved to a file:
>
> import os
> print(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
> print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
>
> As to tests, the only one I can think of would be a pretty horrible one
> involving actually callling out using subprocess.Popen to a python -i of
> the project template settings file, so maybe ok not to bother?
>
> credit to @CleanCut for turning me onto this weirdness!
New description:
ref the default project template's settings.py, BASE_DIR is defined as:
{{{
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
}}}
Because there's no abspath, you can get different results for BASE_DIR
depending on how settings.py is run. This is an edge case, since
settings.py is almost always imported by django in the right context, but
still -- compare:
{{{
python manage.py shell
>>> from django.conf import settings
print(BASE_DIR)
}}}
With:
{{{
python -i myproject/settings.py
>>> print(BASE_DIR)
}}}
As an aside, in general, in any path wrangling you should always call
abspath first. Try running this script, saved to a file:
import os
print(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
As to tests, the only one I can think of would be a pretty horrible one
involving actually callling out using subprocess.Popen to a python -i of
the project template settings file, so maybe ok not to bother?
credit to @CleanCut for turning me onto this weirdness!
--
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:1>
Old description:
> ref the default project template's settings.py, BASE_DIR is defined as:
>
> {{{
> BASE_DIR = os.path.dirname(os.path.dirname(__file__))
> }}}
>
> Because there's no abspath, you can get different results for BASE_DIR
> depending on how settings.py is run. This is an edge case, since
> settings.py is almost always imported by django in the right context, but
> still -- compare:
>
> {{{
> python manage.py shell
> >>> from django.conf import settings
> print(BASE_DIR)
> }}}
>
> With:
>
> {{{
> python -i myproject/settings.py
> >>> print(BASE_DIR)
> }}}
>
> As an aside, in general, in any path wrangling you should always call
> abspath first. Try running this script, saved to a file:
>
> import os
> print(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
> print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
>
> As to tests, the only one I can think of would be a pretty horrible one
> involving actually callling out using subprocess.Popen to a python -i of
> the project template settings file, so maybe ok not to bother?
>
> credit to @CleanCut for turning me onto this weirdness!
New description:
ref the default project template's settings.py, BASE_DIR is defined as:
{{{
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
}}}
Because there's no abspath, you can get different results for BASE_DIR
depending on how settings.py is run. This is an edge case, since
settings.py is almost always imported by django in the right context, but
still -- compare:
{{{
python manage.py shell
>>> from django.conf import settings
print(BASE_DIR)
}}}
With:
{{{
python -i myproject/settings.py
>>> print(BASE_DIR)
}}}
As an aside, in general, in any path wrangling you should always call
abspath first. Try running this script, saved to a file:
{{{
import os
print(os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
}}}
As to tests, the only one I can think of would be a pretty horrible one
involving actually callling out using subprocess.Popen to a python -i of
the project template settings file, so maybe ok not to bother?
credit to @CleanCut for turning me onto this weirdness!
--
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:2>
* status: new => closed
* resolution: => duplicate
Comment:
Duplicate of #21409
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:3>
Comment (by hjwp):
Sorry, should have spotted that. I did do a search for BASE_DIR before
submitting, but it didn't show up...
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:4>
* status: closed => new
* resolution: duplicate =>
Comment:
with due respect, I'm going to tentatively re-open this ticket. #21409
seems to be about changing BASE_DIR to being a different directory,
whereas this ticket asks for BASE_DIR to be an absolute path.
#21409 was closed by @aaugustin, appropriately I think, because BASE_DIR
is exactly where it should be.
But after that, actually, the discussion in #21409 looks like it started
to be about whether the path should be absolute or relative. I couldn't
see any arguments for keeping it relative, and there's definitely an
argument against it (ie, it can cause confusion as per my initial
submission above, and also, it's the default in Python3.4 anyway, so if we
don't do it then that introduces different behaviours for django under
python2 vs 3)
One person did make a case for using joins of `os.pardir` instead of
double path.dirname, which I guess would be fine (although it feels like
the "more semantic" benefit is outweighed by the "harder to read" price).
But in the meantime, I feel like BASE_DIR should definitely be an absolute
path...
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:5>
Comment (by timgraham):
I'm still not sure what problems this would cause in practice. In the
example you give, `python -i myproject/settings.py`, it seems like
`__file__` doesn't return an absolute on Python 3.4 since it's covered by:
"with the sole exception of `__main__.__file__` when a script has been
executed directly using a relative path".
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:6>
* component: Uncategorized => Core (Other)
* stage: Unreviewed => Accepted
Comment:
I don't see what purpose would be served by executing a Django settings
module with `python path/to/settings.py`. Is there a use case for which
this is a proper solution? As Tim explained, we can't cover that case on
Python 3.4+ anyway, so I'm going to ignore it.
For consistency between Python 3.4+ and earlier versions, I'm going to add
the `abspath` call, even thought I'm still convinced it doesn't change
anything, except maybe in contrived made-up examples.
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:7>
Comment (by aaugustin):
I don't want to backport this to 1.7.x because the default settings are
often reproducted in training materials, especially books, and even small
differences can unsettle beginners.
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:8>
* status: new => closed
* resolution: => fixed
Comment:
In [changeset:"caf5cd7ba7c9d73194e394a26c81f1a677d54a6c"]:
{{{
#!CommitTicketReference repository=""
revision="caf5cd7ba7c9d73194e394a26c81f1a677d54a6c"
Fixed #23436 -- Made BASE_DIR absolute in settings template.
This ensures consistency between Python 3.4+ and earlier versions.
Thanks Harry Percival for the report.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/23436#comment:9>