代码之家  ›  专栏  ›  技术社区  ›  Brian Neal

jjango管理命令的python导入问题

  •  4
  • Brian Neal  · 技术社区  · 14 年前

    不管什么原因,当我刚接触到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 在网上宣布 ForeignKey 在models.py中。

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

    from django.contrib.auth.models import User
    
    class MyModel(models.Model):
        user = models.ForeignKey(User)
        # ...
    

    有人能给我解释一下我遗漏了什么吗?当您运行管理命令时,环境中有什么不同吗?还是我一直在做错事?谢谢!

    编辑 :遵循dmitko关于循环导入的预感,这里是在my models.py文件中使用的导入。我展示的是 授权 注释掉,以及唯一具有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
    

    是否设置了循环导入类型的情况?

    3 回复  |  直到 14 年前
        1
  •  5
  •   apenwarr    14 年前

    如果某个随机模块曾经导入模块 x.y.z 后来一个进口 x.y 会看到一个 z X.Y 命名空间。

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

    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
  •  0
  •   dmitko    14 年前

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

    >>> 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 并查看相同的功能列表。当你导入 from django.contrib.auth.models import User 这意味着您要从 auth 包装和它的工作。

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

        3
  •  0
  •   gmarcotte    14 年前

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