[Django]-Using Python's os.path, how do I go up one directory?

394๐Ÿ‘

โœ…

os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))

As far as where the templates folder should go, I donโ€™t know since Django 1.4 just came out and I havenโ€™t looked at it yet. You should probably ask another question on SE to solve that issue.

You can also use normpath to clean up the path, rather than abspath. However, in this situation, Django expects an absolute path rather than a relative path.

For cross platform compatability, use os.pardir instead of '..'.

๐Ÿ‘คforivall

152๐Ÿ‘

To get the folder of a file just use:

os.path.dirname(path) 

To get a folder up just use os.path.dirname again

os.path.dirname(os.path.dirname(path))

You might want to check if __file__ is a symlink:

if os.path.islink(__file__): path = os.readlink (__file__)
๐Ÿ‘คjassinm

94๐Ÿ‘

If you are using Python 3.4 or newer, a convenient way to move up multiple directories is pathlib:

from pathlib import Path

full_path = "path/to/directory"
str(Path(full_path).parents[0])  # "path/to"
str(Path(full_path).parents[1])  # "path"
str(Path(full_path).parents[2])  # "."
๐Ÿ‘คbirnbaum

25๐Ÿ‘

You want exactly this:

BASE_DIR = os.path.join( os.path.dirname( __file__ ), '..' )
๐Ÿ‘คAlan Viars

13๐Ÿ‘

Personally, Iโ€™d go for the function approach

def get_parent_dir(directory):
    import os
    return os.path.dirname(directory)

current_dirs_parent = get_parent_dir(os.getcwd())
๐Ÿ‘คLord Sumner

12๐Ÿ‘

If you prefer a one-liner for getting the parent directory, Iโ€™d suggest this:

import os
    
parent_dir = os.path.split(os.getcwd())[0]

os.path.split() method returns a tuple (head, tail) where tail is everything after the final slash. So the first index is the parent of your absolute path.

๐Ÿ‘คcarlosgg

9๐Ÿ‘

I think the easiest thing to do is just to reuse dirname()
So you can call

os.path.dirname(os.path.dirname( __file__ ))

if you file is at /Users/hobbes3/Sites/mysite/templates/method.py

This will return โ€œ/Users/hobbes3/Sites/mysiteโ€

7๐Ÿ‘

from os.path import dirname, realpath, join
join(dirname(realpath(dirname(__file__))), 'templates')

Update:

If you happen to โ€œcopyโ€ settings.py through symlinking, @forivallโ€™s answer is better:

~user/
    project1/  
        mysite/
            settings.py
        templates/
            wrong.html

    project2/
        mysite/
            settings.py -> ~user/project1/settings.py
        templates/
            right.html

The method above will โ€˜seeโ€™ wrong.html while @forivallโ€™s method will see right.html

In the absense of symlinks the two answers are identical.

7๐Ÿ‘

This might be useful for other cases where you want to go x folders up. Just run walk_up_folder(path, 6) to go up 6 folders.

def walk_up_folder(path, depth=1):
    _cur_depth = 1        
    while _cur_depth < depth:
        path = os.path.dirname(path)
        _cur_depth += 1
    return path   

5๐Ÿ‘

Go up a level from the work directory

import os
os.path.dirname(os.getcwd())

or from the current directory

import os
os.path.dirname('current path')
๐Ÿ‘คJulio CamPlaz

4๐Ÿ‘

To go n folders upโ€ฆ run up(n)

import os

def up(n, nth_dir=os.getcwd()):
    while n != 0:
        nth_dir = os.path.dirname(nth_dir)
        n -= 1
    return nth_dir
๐Ÿ‘คJo3l

3๐Ÿ‘

Iโ€™m surprised handling for an arbitrary number of ".." parent directory tokens in a path string isnโ€™t directly handled for by the os library. Hereโ€™s a quick and dirty function thatโ€™ll give you an absolute path string from a relative one:

def get_abs_from_relpath(relpath:str) -> str:
    ap = os.path.abspath(__file__).split("/")[:-1]
    sp = relpath.split("/")
    sp_start_index = 0
    for slug in sp:
        if slug == "..":
            ap.pop(-1)
            sp_start_index += 1
        else:
            return "/".join(ap+sp[sp_start_index:])

You can call it with open() like this:

with open(get_abs_from_relpath('../../../somedir/myfile.txt')) as f:
    foo = f.read()
๐Ÿ‘คAlan Garcia

2๐Ÿ‘

For a paranoid like me, Iโ€™d prefer this one

TEMPLATE_DIRS = (
    __file__.rsplit('/', 2)[0] + '/templates',
)
๐Ÿ‘คhaterh

2๐Ÿ‘

With using os.path we can go one directory up like that

one_directory_up_path = os.path.dirname('.')

also after finding the directory you want you can join with other file/directory path

other_image_path = os.path.join(one_directory_up_path, 'other.jpg')
๐Ÿ‘คabdullahselek

1๐Ÿ‘

From the current file path you could use:

os.path.join(os.path.dirname(__file__),'..','img','banner.png')

0๐Ÿ‘

Of course: simply use os.chdir(..).

๐Ÿ‘คThe Shwarma

0๐Ÿ‘

Not an answer but a long tangential comment that probably should be made as someone may be led astrayโ€ฆ

The syntax os.path.join( os.path.dirname( __file__ ), 'foo.txt') to get a file within the same folder as the python file getting run is not the "advised" solution for packages, instead package data is preferred for a couple of reasons, for example in a zip packaged package or a more complicated filesystem.

pkg_resources.read_text(__package__, 'foo.txt') was the formerly recommended solution, but will be removed at some point and importlib.resources.read_text(__package__, 'foo.txt') is the recommended way โ€”see https://docs.python.org/3/library/importlib.html#module-importlib.resources for the many options.
However, this

  • requires include_package_data=True and package_data with a Dict[str, List[str] in the setup.py file
  • requires a MANIFEST.in if pip distributed as sdist (but not a built wheel)
  • will not work for relative imports (i.e. not installed)
  • is wisely and generally ignored for sake of sanity in webapps due to the way they run
๐Ÿ‘คMatteo Ferla

Leave a comment