成功导入的类是None,但只有inside方法

时间:2013-08-06 21:02:10

标签: python django django-1.5

我的Django应用程序的models.py中有代码看起来像这样:

from main.models import SmartPrefetchQuerySet

class EventPrivacyManager(SoftDeletablePrivacyManager):
    def get_query_set_for_producer(self, producer):
        return self.get_query_set().filter(users_about=producer)

    def get_query_set(self):
        return SmartPrefetchQuerySet(self.model, using=self._db)

    ...

导入工作正常 - 我可以在模块中print SmartPrefetchQuerySet,输出为<class 'main.models.SmartPrefetchQuerySet'>。但是当我实际调用get_query_set方法时,我得到了这个:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File ".../feeds/models.py", line 29, in smart_prefetch_for
    return self.get_query_set().smart_prefetch_for(*args, **kwargs)
  File ".../feeds/models.py", line 26, in get_query_set
    return SmartPrefetchQuerySet(self.model, using=self._db)
TypeError: 'NoneType' object is not callable

另一方面,如果我在get_query_set方法本身内移动导入,它可以正常工作。如果我打开一个Django shell并通过直接将Event模型传递给它来实例化SmartPrefetchQuerySet,那也可以正常工作。仅在方法内部,SmartPrefetchQuerySet看起来是None(注入该方法的print语句验证该名称确实引用了None)。

“SmartPrefetchQuerySet”名称仅用于该类的类定义,并在此处调用它,并且在代码库中没有其他地方。

我不明白这种行为是如何可行的,因为Python命名空间通常如何工作。如何将导入的名称定义为模块级别的一件事,并且在同一模块中的方法内部完全不同,在模块中的任何位置都没有对该名称的其他分配?到目前为止我唯一的想法是它可能是一个循环导入问题,但我找不到任何这样的循环导入,通常循环导入似乎导致不那么微妙的问题。

编辑:整个models.py文件,有点消毒和缩写:

from django.db import models

from django.conf import settings

from auth.models import HasPrivacy, SoftDeletablePrivacyManager
from lck.django.common.models import TimeTrackable, SoftDeletable
from groups.models import Group

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.utils import timezone

from main.models import SmartPrefetchQuerySet # not literally from a module named "main", but the name has to be sanitized for this post

print SmartPrefetchQuerySet # prints "<class 'main.models.SmartPrefetchQuerySet'>"

# Note: there is an additional import at the bottom of this file for event signal registration

class EventPrivacyManager(SoftDeletablePrivacyManager):
    def get_query_set_for_producer(self, producer):
        "class that can be overridden by children of this manager for models that don't have a 'user' attrib"
        return self.get_query_set().filter(users_about=producer)

    def get_query_set(self):
        print SmartPrefetchQuerySet # prints "None"
        return SmartPrefetchQuerySet(self.model, using=self._db)

    def smart_prefetch_for(self, *args, **kwargs):
        return self.get_query_set().smart_prefetch_for(*args, **kwargs)

class Event(HasPrivacy, SoftDeletable, TimeTrackable):
    ...

    objects = EventPrivacyManager()

    ...

class Notification(SoftDeletable, TimeTrackable):
    ...

print SmartPrefetchQuerySet # prints "<class 'main.models.SmartPrefetchQuerySet'>"

# this import registers the event signal handlers.
# don't remove it even if it doesn't look like it's being used in this
# file, and don't move it from the bottom of this file in order to avoid
# circular imports!
import events

print SmartPrefetchQuerySet # prints "<class 'main.models.SmartPrefetchQuerySet'>"

1 个答案:

答案 0 :(得分:0)

如果用C语言写SmartPrefetchQuerySet,问题可能实际上在调用内,而不是SmartPrefetchQuerySet本身是None。你可以在内置插件中看到类似的结果:

>>> max([1,2], key=None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

检查你传递的内容是什么。