我有一个运行正常的Django应用程序,在过去的几个月里一直运行在DEBUG模式下,当我将网站更改为生产模式时,当我点击一个试图创建新的引用模型对象的特定视图时,我开始收到以下发送给我的异常邮件。
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
正如你所看到的,仅仅是试图示例化一个引用模型对象就会触发这个异常。
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中的一个bug还是我在不知不觉中做了一些我不应该做的事情?有人对修复或变通有什么建议吗?
6条答案
按热度按时间mcdcgff01#
更新(解决方案如下)
我一直在深入研究Django模型代码,似乎有一个bug,当在ForeignKey中使用基于“app.model”的标识符时,会产生一个竞态条件。当应用程序在生产模式下运行而不是在DEBUG下运行时,在上面的异常中引用的ForeignKey.get_default方法会尝试检查提供的默认值是否是相关字段的示例(self.rel.to):
最初,当用基于字符串的相关字段示例化外键时,self.rel.to被设置为基于字符串的标识符。在www.example.com中有一个单独的函数related.py称为add_lazy_relation,在正常情况下,该函数试图将该基于字符串的标识符转换为模型类引用。因为模型是以惰性方式加载的,这个转换可以推迟到AppCache完全加载之后。
因此,如果在AppCache完全填充之前,在基于字符串的ForeignKey关系上调用get_default,则可能会引发TypeError异常。显然,将应用程序置于生产模式足以改变模型缓存的时间,从而导致此错误开始发生。
解决方案
看起来这确实是Django中的一个bug,但是如果你遇到这个问题,这里有一个解决方法。在示例化一个有问题的模型之前,添加下面的代码片段:
这将检查AppCache上的已加载标志,以确定该高速缓存是否已完全填充。如果未完全填充,我们将强制缓存立即完全填充。这样问题就解决了。
s4n0splo2#
在我的例子中,我有一个模型'Entity'和一个继承了'AbstractBaseUser'的'User'。一个'User'模型有一个实体字段,其中实体的ForeignKey是这样配置的:
最后,变通方案是将其更改为
我不知道问题的原因,但它就是那样工作的
x33g5p2x3#
另一个原因:
确保所有的外键都在同一个应用程序(应用程序标签)中的同一个引用模型中。我在这个问题上有一段时间把头撞在墙上。
vqlkdk9b4#
正如在其他答案中已经强调的那样,最常见的原因似乎是引用了使用
'app.Model'
语法的模型。然而,要弄清楚到底是哪个型号造成了麻烦,可能仍然是一个相当大的挑战。
我发现这个问题的一个快速解决方案是直接转到引发异常的位置(
django.db.models.fields.related.ForeignKey.get_default
),然后添加以下print状态现在,有问题的模型的名称已经打印出来,在代码中找到相关位置不再是一个大问题。
在Django 2.2上测试。
eimct9ow5#
在我的例子中,我在类调用中犯了一个错误,用引号把类名括起来。删除引号为我解决了这个错误。请看下面的错误代码:
xfyts7mz6#
在大多数情况下,此错误是由于您在具有模型关系(外键等)的另一个模型中引用已删除/注解的模型而导致的。
1.如果您已删除或注解掉某些模型
1.检查所有的模型是否有外键、一对一等指向已删除的模型
1.注意你在哪里引用模型(下面的例子),因为python不会引发任何明显的错误