实例化Django模型会引发TypeError:isinstance()arg 2必须是类和类型的类,类型或元组

Der*_*rds 9 django django-models

我有一个现有的,功能齐全的Django应用程序,在过去的几个月里一直在DEBUG模式下运行.当我将站点更改为在生产模式下运行时,当我点击试图创建新的Referral模型对象的特定视图时,我开始收到以下异常电子邮件.

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
Run Code Online (Sandbox Code Playgroud)

如您所见,仅尝试实例化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
Run Code Online (Sandbox Code Playgroud)

这是Django中的一个错误,还是我在不知不觉中做了一些我不应该做的事情?任何人有任何修复或解决方法的建议?

Der*_*rds 13

更新(以下解决方案)

我一直在挖掘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
Run Code Online (Sandbox Code Playgroud)

最初,当使用基于字符串的相关字段实例化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()
Run Code Online (Sandbox Code Playgroud)

这将检查AppCache上的已加载标志,以确定缓存是否已完全填充.如果不是,我们将强制缓存现在完全填充.问题将得到解决.

  • 谢谢!我遇到过同样的问题.这是作为Django的门票提交的吗?我在https://code.djangoproject.com/ticket/上找不到任何东西 (2认同)
  • 这太*烦人了.在将站点迁移到自定义用户模型时遇到此问题.好像该过程中没有足够的问题.但是,从硬链接到'User`到`settings.AUTH_USER_MODEL`会导致锁定.我在所有的models.py文件和shazaam中都卸载了这些,这很有效. (2认同)

小智 8

就我而言,我有一个模型“实体”和一个继承“AbstractBaseUser”的“用户”。“用户”模型有一个实体字段,其中外键到实体的配置如下:

entity = m.ForeignKey('core.Entity', on_delete=m.SET_NULL, null=True)
Run Code Online (Sandbox Code Playgroud)

最后解决方法是将其更改为

from core.models import Entity
entity = m.ForeignKey(Entity, on_delete=m.SET_NULL, null=True)
Run Code Online (Sandbox Code Playgroud)

我不知道问题的原因,但它就是这样工作的