Search code examples
djangopycharmdjango-staticfiles

django Pycharm 2020.2.2 not resolving static files when using "pathlib.Path" to address BASE_DIR


I'm using the latest version of Pycharm, 2020.2.2 and django 3.1.

In my project, I removed the default settings.py and created a directory named settings, so the whole project root looks like:

tsetmc
├── asgi.py
├── celery.py
├── context_processors.py
├── __init__.py
├── settings
│   ├── base.py
│   ├── __init__.py
│   ├── local.py
├── urls.py
├── views.py
└── wsgi.py

and in the base.py, I defined the static files setting as:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent.parent

...

STATIC_URL = '/static/'

STATICFILES_DIRS = [
    BASE_DIR / 'assets/'
]

STATIC_ROOT = BASE_DIR / 'staticfiles/'

MEDIA_URL = '/media/'

MEDIA_ROOT = BASE_DIR / 'media/'

Everything works fine in the browser and the static files are successfully loaded using the {% static %} tag; However, Pycharm can not resolve any of the static files in the templates.

I enabled Django Support, set Django project root and settings in the Pycharm settings accordingly and also set the Template Language as Django; but it didn't solve the issue.


After some trial-and-error, I found an odd solution; If I use import os and os.path.join() to locate the static paths, instead of from pathlib import Path and /, Pycharm can resolve the static files without any problem.

So when I changed my base.py to look like this:

import os

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


STATIC_URL = '/static/'

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'assets')
]

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles/')

MEDIA_URL = '/media/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')

(after invalidating the cache, without changing any other configuration)

Pycahrm can fully resolve the static files.

What am I missing here? Is there any problem with using Path to address the static files? or the problem is about the Pycharm itself?

Thanks for the help.


Solution

  • This is a known limitation of PyCharm, you can see this 6 years old bug report: https://youtrack.jetbrains.com/issue/PY-13911. Other users have the same problem, for example here: https://youtrack.jetbrains.com/issue/PY-45244.

    This is the recommended solution:

    Please consider using os.path for BASE_DIR. (...)

    I use https://github.com/pydanny/cookiecutter-django for my projects, which uses pathlib in settings. Even the official Django documentation uses pathlib.

    That's why I use this hack in settings so that PyCharm can autocomplete and I can use pathlib:

    import os
    from pathlib import Path
    
    
    ROOT_DIR = Path(__file__).resolve(strict=True).parent.parent.parent
    
    # my_project/
    APPS_DIR = ROOT_DIR / "my_project"
    
    # STATIC
    # ------------------------------------------------------------------------------
    # https://docs.djangoproject.com/en/dev/ref/settings/#static-root
    STATIC_ROOT = str(ROOT_DIR / "staticfiles")
    
    # https://docs.djangoproject.com/en/dev/ref/settings/#static-url
    STATIC_URL = "/static/"
    
    # https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
    STATICFILES_DIRS = [
        str(APPS_DIR / "static"),
        os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), 'my_project', 'static')
    ]
    

    Django staticfiles autocomplete