Django 1.11
Python 3.6.1
For my project is to be deployed, I will have to predefine some things. Namely, I'll need a couple of groups for users.
So, I made a directory "deployment" and placed it next to the project's directory.
When a new database will be created, I'll just execute:
python manage.py shell < ../deployment/initialize_project.py
This code works:
from django.contrib.auth.models import Group
Group.objects.create(name="commentator") # Can only comment.
Group.objects.create(name="contributor") # Can add, change and delete
# objects.
This code does not:
from django.contrib.auth.models import Group
def initialize_roles():
Group.objects.create(name="commentator") # line 6
Group.objects.create(name="contributor")
initialize_roles() # line 12
Traceback:
Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/home/michael/workspace/venv/photoarchive/lib/python3.6/site-packages/django/core/management/__init__.py", line 363, in execute_from_command_line
utility.execute()
File "/home/michael/workspace/venv/photoarchive/lib/python3.6/site-packages/django/core/management/__init__.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/home/michael/workspace/venv/photoarchive/lib/python3.6/site-packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/home/michael/workspace/venv/photoarchive/lib/python3.6/site-packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/home/michael/workspace/venv/photoarchive/lib/python3.6/site-packages/django/core/management/commands/shell.py", line 101, in handle
exec(sys.stdin.read())
File "<string>", line 12, in <module>
File "<string>", line 6, in initialize_roles
NameError: name 'Group' is not defined
I marked line 6 and 12 in the code above (as inline comments).
I tried to use pdb.set_trace(), but the same error appear. As if pdb is not defined.
I also tried not to feed manage.py on initialize_project.py, but just run python manage.py shell and feed the code line by line. It worked perfectly.
Could you give me a kick here?
ADDED LATER
This works:
def initialize_roles():
from django.contrib.auth.models import Group
Group.objects.create(name="commentator") # Can only comment.
Group.objects.create(name="contributor") # Can add, change and delete
# objects.
initialize_roles()
Unless there is more to what you're doing, this feels like something fixtures are meant to solve. If there is more to it, you can add custom data migrations as part of the initial set up process. That will avoid having to worry about when models are available to you.
I faced similar situation - this behavior is strange, indeed. It looks like inside this function, all the imports are missing (I checked that with dir() - it was empty), but I don't know why. Would be great if someone could answer that.
I don't think it's elegant to keep the script unwrapped by function, and as I was facing the same thing, I found this thread useful (danodonovan's answer): Python Script from Django shell. What he suggests is to create commands subdir, and add a script to it (for instance init_db). Then you can easily run:
./manage.py init_db
This resolves problems stated in your question, but not answers why is it happening. I hope that someone explain that.