blog Brainstorming Django With Javascript

Tags:
django javascript

Similar to how easy it is to run uv add <package> to our python projects, I have recently been brainstorming (hallucinating?) about a workflow for django with javascript libraries.

Adding apps to Django

For an imaginary django-foo app, if we want to install it into our larger Django project, we have a few steps.

  • uv add django-foo to install the Python package to our project.
  • Edit our settings.py to add our foo or foo.apps.Config to INSTALLED_APPS so that Django can load our app.
  • Edit our urls to point to any views we might want to enable.

There are a few projects like djp (built on pluggy ) or my own prototype powerplug to make apps more easily installable. The idea is that using metadata within the package, such as entrypoints .

Adding Javascript to Django

By default, Django has some support for including other staticfiles into your project. Often this will be paired with whitenoise for severing files in a Django app.

While many Django developers may want to avoid npm, for my django-include-bootstrap I used it to help bundle the required js/css files.

For this, I used a Makefile to use npm install to download the version of Bootstrap I was targeting, and then rsync to place it into the correct place.

STATIC_DIR := src/django_include_bootstrap/static/
NODE_MODULES := node_modules/bootstrap/dist/

.PHONY: build
build: $(STATIC_DIR)
	uv build --clear

# Bootstrap Dependencies
$(STATIC_DIR): $(NODE_MODULES)
	rsync -vr --delete $(NODE_MODULES) $(STATIC_DIR)

# Javascript
$(NODE_MODULES): package.json
	npm install

I also needed to include a MANIFEST.in to ensure the static files are included as well

graft django_include_bootstrap/static
graft django_include_bootstrap/templates

HTML Components

This works ok if I am shipping a large library as-is without significant modification, but what if I want to make HTML Components

I would like to find some more blog posts and figure out more best practices around shipping Javascript.

For my django-chart-component I want to implement a way to have chart components implemented as an HTML Component instead of needing to write javascript each time. Since I do not use Javascript on a regular basis, it’s quite confusing to know if I should be using npm by itself, or webpack or vite or something else to compile things.

When I am ready to pick things back up, I’m tempted to wrap ChartJS in a download similar to my django-include-bootstrap and then try something like dj-importmap so that I can write just my element as a javascript module instead of trying to use a bundler.

I have been reading some posts like How I’m using Django, JavaScript modules and importmaps together but would still like to find more information on best practices around shipping Javascript components with Django, without requiring npm by the end user.

Brainstorming the future?

It’s unlikely that we can fully get away from builders an npm (though the django-htmx project uses a download_htmx.py to download the files) but it could be nice to have some common patterns around this.

I am not sure we need a specific cookiecutter template, but perhaps we could have a django-bundle-js command that uses the javascript communities package.json and either wraps npm install or perhaps wraps curl to download the versions from a CDN into our local paths, and assists in maintaining our MANIFEST.in or pyproject package_data entries to remove some of the confusion.

Then when we want to use various javascript components with our Django projects, it would be as easy as installing them using uvx

uvx django-install django-include-bootstrap
uvx django-install django-htmx
uvx django-install django-chart-component

Which would use uv add to add the packages to our pyproject.toml and then automatically register them in our settings.py INSTALLED_APPS entry. With them installed django collectstatic would put all of our javascript and css files in the correct place, and dj-importmap and whitenoise would ensure that any custom components for our own app, can find the references they need.

It could also be argued that this is added complexity, but I think it can be helpful to brain-dump even half baked ideas in the hope that it sparks good ideas elsewhere.