Default automatic imports in the shell

Hello everyone,

The work we have done so far has been great. I hope this new feature will be useful for most Django users. If you want to know more about it, see the related forum post, PR, and ticket.

Now, we are considering how to enhance the automatic imports. We have been discussing whether some default imports, such as django.conf.settings, could be useful for the end-users of the shell. We would appreciate feedback from the community so that we can agree on what should be automatically imported by default, avoiding a multitude of tickets requesting to add default imports.

We are looking forward to your valuable feedback.

2 Likes

django.conf.settings +1
Maybe datetime and django.utils.timezone :thinking:

5 Likes

One thing I keep thinking is missing from shell_plus at the moment is all the ORM bits and bobs. The main reason I use the shell is to test novel queries, so I often am a bit annoyed that I don’t have utilities and functions available, e.g. Subquery / OuterRef, Now / Case /When / Exists etc.

Would really love a star import of all these and more if it doesn’t have the chance to clobber too much stuff

7 Likes

Thank you for starting the discussion @salvo-polizzi , and good work so far on the automatic imports project.

In my experience, the shell is most often used for making or debugging database queries. So I think we should primarily consider imports to make that experience smoother.

For datetime, I propose we do:

from datetime import *
import datetime as dt
from django.utils import timezone

datetime.timezone will be shadowed by django.utils.timezone, hence the dt alias for the datetime module as well. This is a practice I’ve recommended and seen adopted by many: How I Import Python’s datetime Module - Adam Johnson .

For ORM tools, I propose we do @tom’s suggestion:

from django.db.models import *
from django.db.models.functions import *

I don’t think there’s much risk of clobbering/shadowing, because we’re starting with an empty namespace, and we’ll put these default imports before models and anything else users might add.

I’m also +1 to from django.conf import settings. Whilst it’s not ORM-related, I’ve realized I use it fairly often.

I checked through my IPython history for any other key imports. The only one I spotted was from decimal import Decimal I think most projects use DecimalFields, so being able to define values without an import is going to be valuable.

6 Likes

Agreed

Do we think that we need to document everything that is automatically imported or say something along the lines of “the shell has a series of automatic imports to assist making queries, you can see the full list by calling globals()”?

I personally like that currently shell_plus lists all the imports it has automatically performed (and in what order), it means the context for what you are working with is right there on the screen with you with out having to call an extra function or remember which function to call to see the list (I don’t use globals() regularly, if I ever have).

I also mention the order, because there have definitely been a time or two where a project has 2 models name the same thing (from migrating to wagtail if I remember correctly) so listing the order helps to know which, if any, models are currently imported.

This is a good point - discoverable, self-documenting - I do like it (+1)

1 Like

I am against printing all the imports by default, since on even modest projects, they can be hundreds of lines. That’s why I asked @salvo-polizzi to only implement the “N objects imported automatically” message the PR currently has. Perhaps we could enable it with extra verbosity (-v 2) though? It would need some care too since user code can add objects to the namespace that don’t have a sensible import path to display.

I think a small docs section is worth it. Perhaps a sentence about the database queries rationale and a list of the effective import statements being run. globals() will list everything, so it won’t be as compact and understandable as from django.db.models import *.

1 Like

I thought that might be the case, a definite +1 for me for having it available under the verbosity flag

2 Likes

I like the idea of autoimporting extra modules. However, I suggest narrowing the datetime imports, as its usage may not be considered widespread or common in every shell interaction. Specifically, I believe the following would be sufficient:

from datetime import date, datetime, timedelta

I would recommend omitting import datetime as dt. While I acknowledge Adam’s influence and recognize that it may be adopted by many, it still seems somewhat niche to me. I would suggest leaving this option to the user for customization.

Then I would like to suggest that we autoimport get_user_model and define User = get_user_model(), assuming that django.contrib.auth is listed in INSTALLED_APPS. In my experience, the second most common usage of the shell is to make an existing user staff or superuser.

Okay, this is fair. I think it’s more expected at least.

This model will already be added by the automatic model imports already in the PR.

1 Like

Good point, thank you! That makes total sense :star_struck:

One more suggestion I thought of: from django.db import transaction. I had a need the other day to use transaction.atomic() whilst live-coding with the ORM.

@adamchainz What would be a common use case for transaction in the shell?

In my (biased!) experience, the shell is used to inspect queries and see how objects and method behave, but I have not (never!) “debugged” transactions in the shell (I have done so via test cases where I can manually force the interleaving I need). But maybe I’m missing use cases? I would love to know more!

Therefore, I suggest not including from django.db import transaction by default. I believe that most large projects can function effectively without manually defining or managing transactions.

Additionally, I often find myself needing from django.db import connection, reset_queries, but I am hesitant to push for these to be imported by default, as this may enter the realm of personal preferences and habits.