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

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's ~/.jupyter/ while on OSX it’s ~/Library/Jupyter/) 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 what was active at 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:

  • "DJANGO_SETTINGS_MODULE": "my_project.settings": your settings, usually as seen inside your project's manage.py

  • "PYTHONPATH": "$PYTHONPATH:/home/projectuser/projectfolder/my_project": PYTHONPATH is extended to include your project's main directory (the one containing manage.py) so that settings can be found even if the kernel isn't run in that exact directory (here django_extensions will use a generic python, thus running the wrong virtual environment unless the whole Jupyter server is launched from inside it: adding this to the kernel.json created by django_extensions will enable it to run notebooks anywhere in the Django project directory)

  • "/home/projectuser/.pyenv/versions/2.7.15/envs/my_project_venv/bin/python": first argument (argv list) of the kernel execution, should be the full path to your project's virtual environment's python interpreter (this is another thing django_extensions gets wrong: fixing this will allow any notebook server to run that specific Django environment's kernel with all its installed modules)

  • "django_extensions.management.notebook_extension": this is the extension that will load the 'shell_plus' functionality in the notebook (optional but useful :-) )


  1. Install django-extensions from https://github.com/django-extensions/django-extensions/blob/master/docs/index.rst

     pip install django-extensions
    
  2. Change your settings file to include 'django-extensions'

     INSTALLED_APPS += ['django_extensions']
    
  3. Run your Django server like this:

    python manage.py shell_plus --notebook
    
  4. alter to suit, and run this in your first cell

    import os, sys
    PWD = os.getenv('PWD')
    os.chdir(PWD)
    sys.path.insert(0, os.getenv('PWD'))
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "local_settings.py")
    import django
    django.setup()
    
  5. Now you should be able to import your django models etc. eg:

    from app.models import Foobar
    Foobar.objects.all()
    

Here's what just worked for me

  1. install Django Extensions (I used 1.9.6) as per other answers
  2. install jupyter
    pip install jupyter
  3. some stuff I did to setup jupyter inside my Docker container -- see below if this applies to you †
  4. from your base Django directory, create a directory for notebooks, e.g.
    mkdir notebooks
  5. Go to that directory
    cd notebooks
  6. start django extensions shell_plus from inside that directory:
    ../manage.py shell_plus --notebook
    The notebook server should now be running, and may launch a new browser. If it doesn't launch a browser window, follow the instructions to paste a link or a token.
  7. from the browser, open a new "Django Shell Plus" notebook, as per John Mee's answer's screenshot

AND, importantly, what didn't work was changing directories from inside the notebook environment. If I tried to work with any notebook that was not in the directory that manage.py shell_plus --notebook was run in, then the kernal was not configured correctly. For me, having the notebook be configured for just a single directory at a time was good enough. If you need a more robust solution, you should be able set PYTHONPATH prior to starting jupyter. For example add export PYTHONPATH="$PYTHONPATH:/path/to/django/project" to a virtualenv activate script. But I haven't tried this.

† Docker Setup (optional)

  1. add a port mapping for your container for port 8888

For example, in your docker compose file;

ports:
      -  "8890:8888"
  1. Configure your project settings file to use ip 0.0.0.0

This is what I did:

NOTEBOOK_ARGUMENTS = [
    '--ip', '0.0.0.0', 
    '--allow-root',
    '--no-browser', 
]