Django AttributeError:类型对象'User'没有属性'_collect_sub_objects'

时间:2011-04-02 03:39:25

标签: django python-2.6

我正在尝试重新安装一个我几个月没用过的网站,并且收到错误,我似乎无法找到解决方案。

运行django的最新主干,python 2.6。

这是堆栈跟踪:::

[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X] mod_wsgi (pid=9458): Exception occurred processing WSGI script '/home/www/vhosts/site/site.wsgi'.
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X] Traceback (most recent call last):
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/core/handlers/wsgi.py", line 273, in __call__
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     response = self.get_response(request)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/core/handlers/base.py", line 169, in get_response
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/core/handlers/base.py", line 214, in handle_uncaught_exception
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     if resolver.urlconf_module is None:
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/core/urlresolvers.py", line 274, in _get_urlconf_module
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     self._urlconf_module = import_module(self.urlconf_name)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/utils/importlib.py", line 35, in import_module
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     __import__(name)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/home/www/vhosts/site.com/site/urls.py", line 7, in <module>
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     from site.feeds import *
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/home/www/vhosts/site.com/site/feeds.py", line 6, in <module>
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     from site.content.models import *
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/home/www/vhosts/site.com/site/content/models.py", line 14, in <module>
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     from site.authors.models import Author
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/home/www/vhosts/site.com/site/authors/models.py", line 11, in <module>
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     class Author(models.Model):
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/db/models/base.py", line 97, in __new__
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     new_class.add_to_class(obj_name, obj)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/db/models/base.py", line 217, in add_to_class
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     value.contribute_to_class(cls, name)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/db/models/fields/related.py", line 891, in contribute_to_class
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     super(ForeignKey, self).contribute_to_class(cls, name)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/db/models/fields/related.py", line 112, in contribute_to_class
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     self.do_related_class(other, cls)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/usr/lib/python2.6/site-packages/django/db/models/fields/related.py", line 124, in do_related_class
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     self.contribute_to_related_class(other, self.related)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]   File "/home/www/vhosts/site.com/site/utils/nullableforeignkey.py", line 38, in contribute_to_related_class
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X]     setattr(cls, _original_csb_attr_name, cls._collect_sub_objects)
[Fri Apr 01 19:31:00 2011] [error] [client X.X.X.X] **AttributeError: type object 'User' has no attribute '_collect_sub_objects'**

以下是有问题的文件::

from django.db import models, connection

class NullableForeignKey(models.ForeignKey):
    """
    Just like a ForeignKey, but when related objects are deleted this object is
    *not* deleted. As the name implies, this field is always NULLable.
    """

    def __init__(self, *args, **kwargs):
        kwargs['null'] = kwargs['blank'] = True
        super(NullableForeignKey, self).__init__(*args, **kwargs)

    def contribute_to_related_class(self, cls, related):
        super(NullableForeignKey, self).contribute_to_related_class(cls, related)

        # define a method name to map the original `_collect_sub_objects` method to
        _original_csb_attr_name = '_original_collect_sub_objects'
        this_field = self

        def _new_collect_sub_objects(self, *args, **kwargs):
            # NULL out anything related to this object.
            qn = connection.ops.quote_name
            for related in self._meta.get_all_related_objects():
                if isinstance(related.field, this_field.__class__):
                    table = qn(related.model._meta.db_table)
                    column = qn(related.field.column)
                    sql = "UPDATE %s SET %s = NULL WHERE %s = %%s;" % (table, column, column)
                    connection.cursor().execute(sql, [self.pk])

            # Now proceed with collecting sub objects that are still tied via FK
            getattr(self, _original_csb_attr_name)(*args, **kwargs)

        # monkey patch the related classes _collect_sub_objects method.
        # store the original method in an attr named `_original_csb_attr_name`
        if not hasattr(cls, _original_csb_attr_name):
            setattr(cls, _original_csb_attr_name, cls._collect_sub_objects)
            setattr(cls, '_collect_sub_objects', _new_collect_sub_objects)


# Prevent deletion completely if item has related children
from django.db.models import OneToOneField, ObjectDoesNotExist
from django.utils.encoding import StrAndUnicode
from django.utils.translation import ugettext as _

class ForeignKeysExist(StrAndUnicode, Exception):
    def __init__(self, parent, child, field):
        '''
            Arguments:
            parent - parent instance (that contains child records)
            child  - object that have foreign key pointing to the parent instance
            field  - child instance foreign key field name
        '''
        self.parent = parent #parent instance
        self.child = child #child that has reference to this parent
        self.field = field #field in the child class that points to the parent
        self.msg = 'Child record %s.%s exists for %s' % (_(child), _(field), _(parent))
        super(ForeignKeysExist, self)

    def __unicode__(self):
        return self.msg

class NoDeleteCascadeMixin(object):
    """
    Mixin to prevent deletion of model
    if there exists any children
    """

    def delete(self):
        # Copied sanity test from django.db.models.ModelBase.delete
        assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)

        opts = self._meta

        for related in opts.get_all_related_objects():
            rel_accessor = related.get_accessor_name()
            if isinstance(related, OneToOneField):
                try:
                    o = getattr(self, rel_accessor)
                except ObjectDoesNotExist:
                    pass # No item in one to one
                else:
                    raise ForeignKeysExist(related.parent_model._meta.object_name, opts.object_name, related.field.name)
            else:
                rel_manager = getattr(self, rel_accessor)
                if rel_manager.count():
                    raise ForeignKeysExist(related.parent_model._meta.object_name, related.model._meta.object_name, related.field.name)

        super(NoDeleteCascadeMixin, self).delete()

1 个答案:

答案 0 :(得分:2)

查看django源代码,_collect_sub_objects在版本1.2和1.3之间被删除了。请参阅changes


Django现在为ForeignKeys docs提供了 on_delete 选项。

<强> ForeignKey.on_delete

  

删除ForeignKey引用的对象时,Django by   默认模拟的行为   SQL约束ON DELETE CASCADE和   还会删除包含该对象的对象   ForeignKey的。这种行为可以   通过指定on_delete来覆盖   论点。例如,如果你有   可以为空的ForeignKey,你想要它   在引用的对象时设置为null   被删除:

user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)

  

on_delete的可能值是   在django.db.models中找到:

  • CASCADE:Cascade删除;默认。

  • PROTECT:通过引发django.db.models.ProtectedError(django.db.IntegrityError的子类)来防止删除引用的对象。

  • SET_NULL:设置ForeignKey为null;只有当null为True时才可以这样做。

  • SET_DEFAULT:将ForeignKey设置为其默认值;必须设置ForeignKey的默认值。

  • SET():将ForeignKey设置为传递给SET()的值,或者如果传入了callable,则调用它的结果。在大多数情况下,为了避免在导入models.py时执行查询,必须传递一个callable:

    def get_sentinel_user():
        return User.objects.get_or_create(username='deleted')[0]
    
    class MyModel(models.Model):
        user = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
    
  • DO_NOTHING:不采取任何行动。如果数据库后端强制实施参照完整性,除非您手动将SQL ON DELETE约束添加到数据库字段(可能使用初始sql),否则这将导致IntegrityError。