【问题标题】:Python import problem with Django management commandsDjango管理命令的Python导入问题
【发布时间】:2011-04-12 07:55:40
【问题描述】:

无论出于何种原因,当我刚接触 Python 和 Django 时,我在 models.py 文件的顶部写了一些类似这样的导入语句:

from django.contrib import auth

我会这样使用它:

class MyModel(models.Model):
    user = models.ForeignKey(auth.models.User)
    # ...

这很好用。很久以后,我写了一个自定义管理命令,它会这样做:

from myapp.models import MyModel

当我运行我的自定义命令 (python manage.py my_command) 时,这将导致 Python 抱怨模块 auth 在 models.py 中声明 ForeignKey 的行上没有属性 models

为了解决这个问题,我将我的 models.py 更改为更常用的:

from django.contrib.auth.models import User

class MyModel(models.Model):
    user = models.ForeignKey(User)
    # ...

有人可以向我解释我缺少什么吗?运行管理命令时,环境中有什么不同吗?还是我一直都做错了?谢谢!

编辑:根据 dmitko 对循环导入的预感,以下是我的 models.py 文件中使用的导入。我展示了注释掉的 auth 的原始导入,以及唯一具有 auth 用户模型外键的模型:

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)

以下是发现问题的管理命令的导入:

import datetime   
from django.core.management.base import NoArgsCommand 
from core.models import UserLastVisit, AnonLastVisit, Statistic

这是设置循环导入类型的情况吗?

【问题讨论】:

    标签: python django import


    【解决方案1】:

    如果某个随机模块曾经导入模块x.y.z,那么稍后仅导入x.y 的人将在x.y 命名空间中看到z

    发生这种情况的原因是import x.y.z 实际上是三个导入语句合二为一。它的工作原理是这样的:

    x = __internal_import('x')
    x.y = __internal_import('x/y')
    x.y.z = __internal_import('x/y/z')
    

    下次有人执行__internal_import('x/y') 时,他们会得到相同的对象,因为python 足够聪明,不会两次导入相同的对象。该对象已将其z 成员分配给z 模块。

    在您的完整应用程序中,可能您有一个执行import django.contrib.auth.models 的模块。但是您的最小独立程序没有导入该模块,因此从未分配名称。

    (注意:没有 __internal_import 这样的东西。这只是一个说明。真正的函数还有其他名称,您必须查找。)

    【讨论】:

      【解决方案2】:

      我猜如果你这样做 from django.contrib import auth 这意味着你将 auth 包作为模块导入,它导出的内容由 auth 文件夹中的 __init__.py 驱动:

      >>> from django.contrib import auth
      >>> dir(auth)
      ['BACKEND_SESSION_KEY', 'ImproperlyConfigured', 'REDIRECT_FIELD_NAME', 'SESSION_
      KEY', '__builtins__', '__doc__', '__file__', '__name__', '__path__', 'authentica
      te', 'datetime', 'get_backends', 'get_user', 'import_module', 'load_backend', 'l
      ogin', 'logout']
      

      您可以在django\contrib\auth 中查看__init__.py 并查看相同的功能列表。当您导入 from django.contrib.auth.models import User 时,这意味着您正在从 auth 包中导入子模块并且它可以工作。

      顺便说一句。在任何情况下我都无法使用auth.models.User - 无论是从控制台还是从我的 django 应用程序运行。

      【讨论】:

      • 嗯。感谢您的回复,我会再研究一下。不过,我希望我能解释为什么在我编写管理命令之前使用 auth.models.User 对我有用。
      【解决方案3】:

      如果没有看到您添加的新 manage.py 命令,很难准确地说出发生了什么。但是,我经常在循环导入的情况下看到“没有属性”,并且几乎总是通过将模块级导入更改为函数或类级导入来修复,就像您在此处所做的那样。你可以检查这里是否发生了类似的事情。

      【讨论】:

      • 我已经编辑了我的问题,显示了我希望是代码的相关部分。我认为没有进行循环导入,但您有没有发现任何可疑之处?
      猜你喜欢
      • 2017-01-29
      • 1970-01-01
      • 1970-01-01
      • 2012-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-29
      • 2012-05-01
      相关资源
      最近更新 更多