我的 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 的方法内部(注入该方法的打印语句验证该名称确实指的是 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'>"