Forums

How to run IPython notebook with django-extensions's shell_plus --notebook?

Hi,

From console I can run ./manage.py shell_plus without any problem. Now I want to make a IPython notebook with the exact same functionality but I have trouble initialising it. Any suggestions?

I am not familiar with shell_plus. What does shell_plus do?

It basically preloads shell with all of the models and commonly used functions. Here is more info: https://django-extensions.readthedocs.io/en/latest/shell_plus.html

It's just quality of life thing.

If this is not possible, how to run the django's shell itself from within IPython notebook? I couldn't get it to work.

This sounds the easiest, but if you check just above that answer, there is also the exact code you could run etc, in which case you could customize and pre-import models etc.

The problem is that I cannot create a notebook from within the console itself. The `./manage.py shell_plus --notebook' attempts to create a new kernel and I get the error:

[C 07:39:20.431 NotebookApp] Bad config encountered during initialization:
[C 07:39:20.431 NotebookApp] The 'kernel_spec_manager_class' trait of <notebook.notebookapp.NotebookApp object at 0x7f84494eb745> instance must be a type, but 'environment_kernels.EnvironmentKernelSpecManager'
 could not be imported

Just installing django-extensions is not enough as per the answer you sent; you actually need to run the manage command too...

Shell-plus looks pretty neat! Unfortunately I suspect it won't work on our system right now. If it's trying to actually start up a kernel for an IPython notebook then it won't work, because notebooks run on different machines -- and if it's trying to generate a kernel spec so that you can select "My Django stuff" or something similar from the kernel dropdown in a notebook, then that error would suggest that it's not compatible with the version of notebooks that we have installed.

If you want to run Django stuff inside a notebook, two options come to mind:

  • If you want to simply run existing management commands, then you could just use the ! escape to run them as shell commands, for example !python /path/to/manage.py mycommand.
  • If you want proper access to the Django models and so on, you could configure Django in a cell near the top of your notebook, with code something like this:
    import os
    import sys
    sys.path.append("/path/to/django/project")
    os.environ['DJANGO_SETTINGS_MODULE'] = 'something.settings'
    import django
    django.setup()
    

Ok so I've managed to duplicate the behaviour of django-extension's shell_plus in notebook. Code below:

import sys; print('Python %s on %s' % (sys.version, sys.platform))
import django; print('Django %s' % django.get_version())
sys.path.append("PATH TO DJANGO PROJECT")
os.environ['DJANGO_SETTINGS_MODULE'] = 'SETTINGS FILE'
os.environ['SECRET_KEY'] = 'SOME SECRET KEY'
if 'setup' in dir(django): django.setup()
from django_extensions.management.shells import import_objects
globals().update(import_objects({"dont_load":[], "quiet_load":False},no_style()))

This will import all of the project models (incl. built in, such as User or Permission; but also third party such as django allauth). It will also include QOL functions, such as get_user_model. The list of imports is below:

# Shell Plus Model Imports
<DJANGO BUILT IN, PROJECT, AND THIRD PARTY MODELS> (project and third party model imports are omitted here)
from django.contrib.admin.models import LogEntry
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.contrib.flatpages.models import FlatPage
from django.contrib.redirects.models import Redirect
from django.contrib.sessions.models import Session
from django.contrib.sites.models import Site
# Shell Plus Django Imports
from django.core.cache import cache
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import transaction
from django.db.models import Avg, Case, Count, F, Max, Min, Prefetch, Q, Sum, When, Exists, OuterRef, Subquery
from django.utils import timezone
from django.urls import reverse

The huge advantage of this approach is that when new models are added to the project you don't have to change your notebook cell at all; it will just import them automatically.

That's pretty nifty -- thanks for sharing!