kevin1024/django-npm

npm_install not working on Windows

Closed this issue · 10 comments

Hey all, I have a Django project with npm dependencies running on a virtualenv python 3.5 on my Windows 10 machine. I tried following the README, double checking my steps several times.

However, this keeps showing up whenever I call npm_install()
image

This is the code I'm using in app/settings.py:

NPM_ROOT_PATH = os.path.join(BASE_DIR, "static")

STATICFILES_FINDERS = [
    npm.finders.NpmFinder
]

npm.finders.npm_install()

Any ideas as to what's going on here? The NPM_ROOT_PATH is correct as doing an os.listdir() on it shows the package.json file so my guess is that it isn't finding the correct path for npm.

For now I'm mitigating the issue by writing this in my manage.py file:

subprocess.call([shutil.which("npm"), "install", "--prefix", "static/", "static/"])

But I'd rather have as a module whose settings can be set in settings.py.

Thanks for your help!

I'm not sure it will help, but you should ADD the npm finder to the list STATICFILES_FINDERS. In the previous example you override the default finder.
Otherwise the config seems correct.

Why have you static/ twice in your custom command?
Could you print the complete value of the command there : https://github.com/kevin1024/django-npm/blob/master/npm/finders.py#L17 ?

Just for a data point, it forks for me on Win10 / Python 3.

The following is in my settings.py, may be relevant:

if platform.system() == 'Windows':
    NPM_EXECUTABLE_PATH = r'C:\Program Files\nodejs\node_modules\npm\bin\npm.cmd'

Hey all, thanks for the quick responses.

@raphael-boucher

  • STATICFILES_FINDERS isn't defined by default in my settings.py. That's why I'm setting it.
  • I have static twice to have npm read static/package.json and install into static/node_modules. That methodology doesn't rely on ./manage.py collectstatic. You guys should probably do that too. BTW, I had tried with the packages.json file in both the root and static/ directories and the appropriate prefix set with the same issue.
  • Sure thing. Here's the output:

['npm', 'install', '--prefix=C:\\Users\\Josue Rios\\Desktop\\UndocuScholar\\static']

@mvasilkov I wouldn't rely on that exact path as it could be different on another Windows machine. I would do

from shutil import which
NPM_EXECUTABLE_PATH = which('npm')

since which() grabs the path for npm regardless of the OS.

What I mean is that by redefining STATICFILES_FINDERS, you override the default values : https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-STATICFILES_FINDERS
You should do something like STATICFILES_FINDERS.append('npm.finders.NpmFinder').

If you go in the directory of your package.json and do a subprocess.call with the arguments of the output you stated in your previous post, does it work?
This projet does not allow (yet) to install from a package.json without being in the directory, a good step would be to have your command work when it is.

I suppose that'd be a valid point if I didn't get NameError: name 'STATICFILES_FINDERS' is not defined. Do you know what package it's part of to import it?

Yes that command does work in the directory, assuming the spaces are escaped, and I believe the subprocess module does escape the spaces or put the argument in quotes.

Actually, I don't think it's possible to override them this way, my bad. It looks like the options needs to be redefined in the settings file.
You can see here the default values : https://docs.djangoproject.com/en/1.10/ref/settings/#staticfiles-finders
By the way at the top of this page :

Be careful when you override settings, especially when the default value is a non-empty list or dictionary, such as MIDDLEWARE_CLASSES and STATICFILES_FINDERS. Make sure you keep the components required by the features of Django you wish to use.

In your case :

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'npm.finders.NpmFinder',
]

Ah, that makes perfect sense. Thanks.

However, the original error persists.

I don't have the answer here. A good way to start would be to try the simplest setup, with package.json at the root of the projet, no prefix, and add the options gradually to identify which one causes the issue.

We have got similar problem on windows.

Not working: NPM_STATIC_FILES_PREFIX = 'js/lib'
Working: NPM_STATIC_FILES_PREFIX = os.path.join('js', 'lib')

Thanks for the update!
I consider this solution good enough to close, feel free to re-open if necessary.