djangojupyter-notebookipythonjupyter

How do I set up Jupyter/IPython Notebook for Django?


I have been using the method described in this post for setting up IPython Notebook to play nicely with Django. The gist of the method is to create an IPython extension which sets the DJANGO_SETTINGS_MODULE and runs django.setup() when IPython starts.

The code for the extension is:

def load_ipython_extension(ipython):
    # The `ipython` argument is the currently active `InteractiveShell`
    # instance, which can be used in any way. This allows you to register
    # new magics or aliases, for example.
    try:
        import os
        os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
        import django
        django.setup()
    except ImportError:
        pass

With a recent upgrade to Jupyter Notebook this setup is now broken for me. I am able to run Django code in the Jupyter notebook by adding a similar bit of code to the first cell of the notebook. However, I was not able to figure out how to get Jupyter to run the extension automatically so I would not have to do this again for each and every notebook I am creating.

What should I do to get Django and Jupyter to play nicely?

UPDATE: For @DarkLight - I am using Django 1.8.5 with Jupyter 1.0.0. The code I run in the notebook is:

import os, sys
sys.path.insert(0, '/path/to/project')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settingsfile")
import django
django.setup()

Solution

  • Just for completeness (but it's 2018, so maybe things changed since this question was posted): you can actually install a Jupyter Python kernel in your Django environment that will then connect (run under) a different Jupyter server/environment (one where you've installed widgets, extensions, changed the theme, etc.). django_extensions right now still does only part of the required work :-)

    This assumes you have a Jupyter virtual environment that's separate from Django's one and whose kernels/extensions are installed with --user. All the Jupyter extensions (and their dependencies) are installed in this venv instead of the Django's one/ones (you'll still need pandas, matplotlib, etc. in the Django environment if you need to use them together with Django code).

    In your Django virtual environment (that can run a different version of Python, including a version 2 interpreter) install the ipython kernel:

    pip install -U ipykernel
    ipython kernel install --user --name='environment_name' --display-name='Your Project'
    

    This will create a kernel configuration directory with the specified -–name in your user’s Jupyter kernel directory (on Linux it was ~/.jupyter/kernels but in 2023 it became ~/.local/share/jupyter/kernels/, while on OSX it’s ~/Library/Jupyter/kernels) containing its kernel.json file and images/icons (by default the default Jupyter icon for the kernel we’re installing are used). This kernel will run inside the virtual environment that was active at kernel creation, thus using the exact same version of python and all the installed modules used by our Django project.

    Running ./manage.py shell_plus --notebook does something very similar, but in addition to requiring everything (including the Jupyter server and all the extensions) installed in the current venv, it’s also unable to run notebooks in directories different from the project’s root (the one containing ./manage.py). In addition it’ll run the kernel using the first executable called python it finds on the path, not the virtual environment’s one, making it misbehave when not started from the command line inside an active Django virtual environment.

    To fix these problems so that we're able to create a Notebook running inside any Django project we have so configured and to be able to run notebooks stored anywhere on the filesystem, we need to:

    1. make sure the first ‘argv’ parameter contains the full path to the python interpreter contained in the virtual environment
    2. add (if not already present) an ‘env’ section that will contain shell environment variables, then use these to tell Python where to find our project and which Django settings it should use. We do this by adding something like the following:
       "env": {
          "DJANGO_SETTINGS_MODULE": "my_project.settings",
          "PYTHONPATH": "$PYTHONPATH:/home/projectuser/projectfolder/my_project"
       }
    
    1. optional: change ‘display_name’ to be human friendly and replace the icons.

    editing this environment kernel.json file you'll see something similar:

    {
     "display_name": "My Project", 
     "language": "python", 
     "env": {
      "DJANGO_SETTINGS_MODULE": "my_project.settings",
      "PYTHONPATH": "$PYTHONPATH:/home/projectuser/projectfolder/my_project"
     },
     "argv": [
      "/home/projectuser/.pyenv/versions/2.7.15/envs/my_project_venv/bin/python", 
      "-m", 
      "ipykernel_launcher", 
      "-f", 
      "{connection_file}",
      "--ext",
      "django_extensions.management.notebook_extension"
     ]
    }
    

    Notable lines: