Django how to use npm modules with static/ templates - django

I have recently added npm to my project in order to keep better track of my js dependencies. Previously I have just been git cloning to my static/vendor folder.
I've also added gulp , but have only got it doing hello world things right now. It seems simple enough - it can watch files, minify assets, compile Sass. Eventually I will probably switch to Webpack, but gulp is simple and working for now. I don't want to use django-compressor or django-pipeline.
So let's say I run npm install vis to pull in visjs. It gets added to node_modules and a record is added to package.json dependencies.
A) Do I reference vis/dist right where it is in node_mods in my template scripts?
<script src="/node_modules/vis/dist/min-vis.js' %}"></script>
# right now it's <script src="{% static 'vendor/min-vis.js' %}"></script
B) Should gulp be listening for changes to package.json dependencies and replicating vis/dist to static/vendor or static/js when it sees changes there?
I keep seeing people talking about handling STATICFILE_DIRS when they talk about npm and gulp. Right now mine is just set to the following. Will this change?
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)

STATICFILES_DIRS tells Django where to find all the static assets (which will later be "collected" for a deployment, but we can ignore that for the moment). That setting will need to include wherever you have gulp placing the processed assets, or you can have gulp put them into $BASE_DIR/static to avoid changing your setting if you prefer.
From there, you should be using the static templatetag
{% load static %}
<script src="{% static 'your_bundled_asset.min.js' %}"></script>
Note that if your asset is in a nested directory under the STATICFILES_DIRS entry it is under, you may need to prefix that. {% static 'js/asset.min.js' %}.
So Django can use the dev location ($BASE_DIR/static) or the "collected" location when deployed (./manage.py collectstatic --noinput pulls all static files to one location for simplified serving).

Related

How do I overwrite Bootstrap SCSS variables for my django website using PyCharm?

I'm using PyCharm to manage my django files and for the front end I'm using Bootstrap. I'm currently using the CDN method to point to the bootstrap files in my base.html file.
I've recently come to a point where I want to customize some of the SCSS variables that bootstrap provides, but I'm puzzled and can't find a guide anywhere to how to do this with my configuration.
I used npm to install the bootstrap files to my outer project folder. I've tried installing django-sass-compiler using pip, and then adding the required setting to my settings.py, but when I ran the command "python manage.py sass-compiler" (as per the PyPi docs), I got "ModuleNotFoundError: No module named 'django_sass_compiler'"
I'm assuming that if I were to get that working then it would compile my custom SCSS file into a CSS file that would overwrite my current 'main.css' (is that right?), however I can't even figure out that part.
If someone could please point me in the right direction then that would be great, there really isn't a lot of help out there for sass, pycharm, django & bootstrap together.
Yes, you will have to compile the CSS manually. You can use tools like Koala.
To accomplish that in Django, You will have to:
Create a directory named static at your project level directory. In satic add another folder called css. Go ahead and add the compiled CSS file.
Change
STATIC_URL = 'static/'
to
STATIC_URL = '/static/'
and add
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
)
In your base.html file at the very top add
{% load static %}
and you can link the base.html file to your compiled CSS file like shown below:
<link rel="stylesheet" href="/static/css/mycss.css">

How to use node modules with Django?

I wish to use date-fns in my django project but not entirely sure how to proceed - I cannot rely on a CDN and need to somehow get it installed. I have run npm init in my root folder followed by npm install date-fns. This generated a node_modules folder and a package.json file.
Not entirely sure how to proceed after this. What are the necessary steps?
Do I just use
<script src="{% static 'node_modules/date-fns' %}"></script>
in my base.html file?
The search path used when the static template operator is used is defined in the settings.py file in STATICFILES_DIR (docs). This will allow the static operator to find the library files and generate the URL.
Note, however, that the files still need to be served by the web server from the expected path defined by STATIC_URL. The manage.py tool in the project root includes a command collectstatic that can copy all of the static search directories into one location to make serving those files simpler.
Also note that you showed a code sample that references the npm library directory from the script tag as a script, but that the browser will not know how to find the script from the directory. node usually uses the library's package.json to find the entry point. It will be necessary to specifically call out the script files of interest inside the package.
One option is to use a bundling tool like webpack or rollup to collect all of the resources into a single location.
Another option is to add the node_modules paths to the static path, perhaps with prefixes. It might look something like the following.
STATIC_URL = '/static/'
STATIC_ROOT = 'dist/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR, 'static'),
# This defines a prefix so the url paths will become `/static/node_modules/...`
('node_modules', os.path.join(BASE_DIR, 'node_modules/')),
)
Specifically include index.js rather than just date-fns from the template file.
{% load static %}
<!-- .... -->
<script src="{% static 'node_modules/date-fns/index.js' %}"></script>
If collecting and serving static files from STATIC_ROOT the following command would collect the STATICFILES_DIRS contents, in this example, into dist/static.
python manage.py collectstatic

Why we need `django-webpack-looader` to serve Vue SPA application through django?

I want to serve my Vue application (as SPA) through django, and I passed across this article. The author use django-webpack-loader to achieve this, but is not adding a simple TemplateView around dist/index.html will do the job:
url(r'^app/', TemplateView.as_view(template_name='index.html'), name='app'),
also this require altering settings.by as follow:
'DIRS': [
BASE_DIR + "/templates/",
BASE_DIR + "/dist/",
]
My question is what is the role of django-webpack-loader in the process if the app is already build using vue-cli?
After trying my approach without django-webpack-loader, I concluded that after each build, you have to do the following:
Put your entry-point (index.html), in a place that django can find it.
Put your assets (css, js, images) in the static folder.
Edit your index.html so it can correctly locate and load the scripts and css files, e.g:
<script src=/js/chunk-vendors.618e754e.js></script>
<script src=/js/app.bbfdaab6.js></script>
Should be:
<script src="{% static 'js/app.bbfdaab6.js' %}"></script>
<script src="{% static 'js/chunk-vendors.618e754e.js' %}"></script>
So django-webpack-loader should helps you with automating this task. without going through django staticfiles system.
Also I have read that django-webpack-loader can provide hot-code reloading during development but I did not try this out. Also I could not find information on how django-webpack-loader works really, so consider this answer incomplete.

No CSS and JS files when deploying with Heroku

I'm trying to deploy my project to heroku, but I faced a problem: there is no CSS and JS in deployed site. When I open page source of deployed site, for example here is next script in page source:
<script type="text/javascript"
src="/static/static/scripts/validation.js">
When I go to src link, it shows internal error. I guess that if my scripts were saved somewhere in Inet and src would be a link to it, then it would work correct. But when deploying my site, all my scripts and CSSare in static folder. When run site locally, it's okay, when through heroku, it can't see CSS and scripts. Is there any solution for it?
Instead of relative path linking use static template tag.
{% load staticfiles %}
<script type="text/javascript" src="{% static "somepath/validation.js" %} ">
set STATIC_ROOT and run python manage.py collectstatic
Check the Heroku doc for Django and Static Assets
Official documentation for Managing static files.

pip: dependency on javascript library

Dependencies to other python libraries can be declared by pip's requirements.txt.
But is it possible to declare a dependency to a pure js library?
The library is available from github. The files should be downloaded an made available for django static file handling.
Background: setting up new development environments of a custom django application should be easy.
How do you handle this in your development environment?
As pointed out by #guettli you can use fanstatic packages.
E.g. requirements.txt
django
js.jquery
js.bootstrap
js.underscore
# ...
without django-fanstatic:
Then in your settings.py you can have:
import js
STATICFILES_DIRS = (
('js', js.__path__[0]),
)
And this is what I have in my base template:
<script src="{{ STATIC_URL }}js/jquery/resources/jquery.min.js"></script>
<script src="{{ STATIC_URL }}js/underscore/resources/underscore-min.js"></script>
<script src="{{ STATIC_URL }}js/bootstrap/resources/js/bootstrap.min.js"></script>
with django-fanstatic:
django-fanstatic
provides a middleware to change the WSGI response. Some more info in this blog post.
pip install only python packages, so if you want to install a Javascript library, you should create a package that contains only the javascript library (declared as additional files).
Not sure if this is really mighty to do this.
Fanstatic already creates a lot of javascript packages (jquery, bootstrap, ...)
You can use the packages without using fanstatic ...
http://www.fanstatic.org/en/latest/libraries.html