This year, I’ve really started to like jupyter notebooks. I first tried them out several years ago, but they’ve only just started to click for me. They haven’t changed; the difference is how I think about them. When I initially tried them, they felt like writing untestable code in a browser, where you could get yourself into an unknowable state very easily as you navigated between cells. While they certainly can be that, it was an incomplete impression, at best.

One thing changed my mind: earlier this year, I learned about the --notebook option for django-extensions shell_plus management command. shell_plus is a command that gives you a REPL with all your django models and many of the framework’s utility classes imported and ready to go. The --notebook option has shell_plus import that all into a jupyter notebook that you can access from your browser. Or that you can save and access from your IDE’s notebook support. It’s like absolute magic when it works, but lately you have to hold your jaw just right and explicitly specify a few dependencies' versions in order to make it work. It was 15 minutes of internet searching every time I felt like I was going to spend enough time in my REPL to want it. I recently learned about dj-notebook, which fixes that and adds a few useful features on top of it.

dj-notebook gives me the REPL I’ve always wanted for django. I use poetry to manage my projects and PyCharm Pro to work on them. Here’s how I use dj-notebook.

  1. Add dj-notebook to my development dependencies.

For me, that means poetry add -D dj-notebook at the root level of my project, but you can use pip or even the PyCharm built-in package management GUI.

  1. Create a new jupyter notebook.

I like to do this by right-clicking my project in PyCharm and choosing New > Jupyter Notebook, and naming it repl.ipynb.

Creating a notebook in pycharm

  1. Import dj-notebook and activate my django project. Now I can use this notebook as a REPL where I can save and reload state, use PyCharm’s autocomplete, refactor and debugging features, and do things like create diagrams for documentation I’m working on.

Using a notebook as a REPL

By doing it this way, I get all the niceties PyCharm’s editor provides in the notebook, I can easily save my “REPL’s” state, and when I make changes, it’s two clicks to restart my “REPL” and re-run all the cells so that it’s back to where I left it.

Reload and run cells

When I set out to add a feature to a project, my usual workflow is to use the django shell (generally the shell_plus one) to iterate and figure out the contours of what I need to do. Replacing that with a notebook is a real accelerant, and having it be so low-friction means I don’t need to weigh the ceremony that’s usually associated with getting jupyter working together with django.

I’m very grateful to Daniel Roy Greenfeld for making and finding a way to release dj-notebook to the world. I’m also glad that TheEpicDev decided to post about this month’s virtual sprint on the django subreddit. I wouldn’t likely have learned about the project otherwise. And by the time I figured out how to add it to a PyCharm project, I had answered my own questions about what it added beyond shell_plus --notebook.

If I can figure out how to add a notebook to my cookiecutter so that it works without weird surprises, this will definitely be going into my django cookiecutter. It’s a large and welcome addition to my workflow. (It’s only large in terms of impact… it was very easy to add to my toolbox.)