For whatever reason, when I was new to Python and Django, I wrote some import statements like this at the top of a models.py file:
from django.contrib import auth
And I'd use it like this:
class MyModel(models.Model):
user = models.ForeignKey(auth.models.User)
# ...
This worked fine. A long time later, I wrote a custom management command, and it would do this:
from myapp.models import MyModel
When I ran my custom command (python manage.py my_command
) this would result in Python complaining that the module auth
had no attribute models
on the line declaring the ForeignKey
in models.py.
To work around this problem, I changed my models.py to the more usual:
from django.contrib.auth.models import User
class MyModel(models.Model):
user = models.ForeignKey(User)
# ...
Can someone explain to me what I am missing? Is there something different in the environment when you run a management command? Or was I just doing it wrong the whole time? Thanks!
Edit: Following dmitko's hunch about circular imports, here are the imports used in my models.py file. I'm showing the original import of auth
commented out, along with the only model that has a foreign key to the auth user model:
import datetime
from django.db import models
# from django.contrib import auth
from django.contrib.auth.models import User
class UserLastVisit(models.Model):
# user = models.ForeignKey(auth.models.User, unique=True)
# ^^^^^^^^^^^^^^^^
# after adding mgmt command, error occurred here; change to the line below
user = models.ForeignKey(User, unique=True)
last_visit = models.DateTimeField(db_index=True)
And here are the imports of the management command that uncovered the problem:
import datetime
from django.core.management.base import NoArgsCommand
from core.models import UserLastVisit, AnonLastVisit, Statistic
Was this setting up a circular import type situation?
The parameter parser is an instance of argparse. ArgumentParser (see the docs). Now you can add as many arguments as you want by calling parser 's add_argument method. In the code above, you are expecting a parameter n of type int which is gotten in the handle method from options .
django-admin is Django's command-line utility for administrative tasks. This document outlines all it can do. In addition, manage.py is automatically created in each Django project.
It is your tool for executing many Django-specific tasks -- starting a new app within a project, running the development server, running your tests... It is also an extension point where you can access custom commands you write yourself that are specific to your apps.
If some random module ever imports module x.y.z
, then a later person who imports just x.y
will see a z
in the x.y
namespace.
The reason this happens is that import x.y.z
is actually three import statements in one. It works something like this:
x = __internal_import('x')
x.y = __internal_import('x/y')
x.y.z = __internal_import('x/y/z')
Next time someone does __internal_import('x/y')
, they'll get the same object, because python is smart enough not to import the same one twice. That object already has its z
member assigned to the z
module.
In your full app, probably you had a module that did import django.contrib.auth.models
. But your minimal standalone program didn't import that module, so the name was never assigned.
(Note: there's no such thing as __internal_import
. It's just an illustration. The real function has some other name that you would have to look up.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With