我有一个现有的、功能强大的 Django 应用程序,它在过去几个月一直在 Debug模式下运行。当我将站点更改为在生产模式下运行时,当我点击尝试创建新引用模型对象的特定 View 时,我开始收到发送给我的以下异常电子邮件。
Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/contrib/auth/decorators.py", line 20, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/var/django/acclaimd2/program/api.py", line 807, in put_interview_request
referral = Referral()
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/db/models/base.py", line 349, in __init__
val = field.get_default()
File "/usr/local/lib/python2.7/dist-packages/Django-1.4.2-py2.7.egg/django/db/models/fields/related.py", line 955, in get_default
if isinstance(field_default, self.rel.to):
TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
如您所见,仅尝试实例化一个 Referral 模型对象就会触发此异常。这是有问题的模型:
class Referral (models.Model):
opening = models.ForeignKey(Opening,related_name='referrals',null=False,blank=False)
origin_request = models.ForeignKey('common.request',related_name='referrals',null=True,default=None)
candidate = models.ForeignKey(User,related_name='referrals',null=False,blank=False)
intro = models.TextField(max_length=1000,null=False,blank=False)
experience = models.TextField(max_length=5000,null=False,blank=False)
email = models.CharField(max_length=255,null=False,blank=False)
phone = models.CharField(max_length=255,null=False,blank=True,default='')
def __unicode__(self):
return u"%s" % self.id
这是 Django 中的错误还是我在不知不觉中做了一些我不应该做的事情?有人对修复或解决方法有任何建议吗?
最佳答案
更新 (下面有解决方案)
我一直在研究 Django 模型代码,似乎有一个错误会在对 ForeignKey 中的相关字段使用基于“app.model”的标识符时创建竞争条件。当应用程序在生产模式而不是 DEBUG 下运行时,上面异常中引用的 ForeignKey.get_default 方法会尝试检查提供的默认值是否是相关字段 (self.rel.to) 的实例:
def get_default(self):
"Here we check if the default value is an object and return the to_field if so."
field_default = super(ForeignKey, self).get_default()
if isinstance(field_default, self.rel.to):
return getattr(field_default, self.rel.get_related_field().attname)
return field_default
最初,当使用基于字符串的相关字段实例化 ForeignKey 时,self.rel.to 被设置为基于字符串的标识符。在related.py 中有一个单独的函数叫做add_lazy_relation,在正常情况下,它会尝试将这个基于字符串的标识符转换为模型类引用。因为模型是以惰性方式加载的,所以这种转换可能会推迟到 AppCache 完全加载。
因此,如果在完全填充 AppCache 之前在基于字符串的 ForeignKey 关系上调用 get_default,则可能会引发 TypeError 异常。显然,将我的应用程序置于生产模式足以改变模型缓存的时间,这个错误开始发生在我身上。
解决方案
看起来这确实是 Django 中的一个错误,但是如果您遇到这个问题,这里是如何解决它的。在实例化一个麻烦的模型之前立即添加以下代码片段:
from django.db.models.loading import cache as model_cache
if not model_cache.loaded:
model_cache._populate()
这会检查 AppCache 上的加载标志以确定缓存是否完全填充。如果不是,我们将强制缓存现在完全填充。而问题将得到解决。
关于django - 实例化 Django 模型会引发 TypeError : isinstance() arg 2 must be a class, 类型,或类和类型的元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14386536/