这段代码在 django/db/models/fields.py 它创建/定义了一个异常?
class ReverseSingleRelatedObjectDescriptor(six.with_metaclass(RenameRelatedObjectDescriptorMethods)): # This class provides the functionality that makes the related-object # managers available as attributes on a model class, for fields that have # a single "remote" value, on the class that defines the related field. # In the example "choice.poll", the poll attribute is a # ReverseSingleRelatedObjectDescriptor instance. def __init__(self, field_with_rel): self.field = field_with_rel self.cache_name = self.field.get_cache_name() @cached_property def RelatedObjectDoesNotExist(self): # The exception can't be created at initialization time since the # related model might not be resolved yet; `rel.to` might still be # a string model reference. return type( str('RelatedObjectDoesNotExist'), (self.field.rel.to.DoesNotExist, AttributeError), {} )
这是在 django/db/models/fields/related.py 它引发了上述异常:
def __get__(self, instance, instance_type=None): if instance is None: return self try: rel_obj = getattr(instance, self.cache_name) except AttributeError: val = self.field.get_local_related_value(instance) if None in val: rel_obj = None else: params = dict( (rh_field.attname, getattr(instance, lh_field.attname)) for lh_field, rh_field in self.field.related_fields) qs = self.get_queryset(instance=instance) extra_filter = self.field.get_extra_descriptor_filter(instance) if isinstance(extra_filter, dict): params.update(extra_filter) qs = qs.filter(**params) else: qs = qs.filter(extra_filter, **params) # Assuming the database enforces foreign keys, this won't fail. rel_obj = qs.get() if not self.field.rel.multiple: setattr(rel_obj, self.field.related.get_cache_name(), instance) setattr(instance, self.cache_name, rel_obj) if rel_obj is None and not self.field.null: raise self.RelatedObjectDoesNotExist( "%s has no %s." % (self.field.model.__name__, self.field.name) ) else: return rel_obj
问题是这段代码:
try: val = getattr(obj, attr_name) except related.ReverseSingleRelatedObjectDescriptor.RelatedObjectDoesNotExist: val = None # Does not catch the thrown exception except Exception as foo: print type(foo) # Catches here, not above
不会捕获该异常
>>>print type(foo) <class 'django.db.models.fields.related.RelatedObjectDoesNotExist'> >>>isinstance(foo, related.FieldDoesNotExist) False
和
except related.RelatedObjectDoesNotExist:
引发AttributeError: 'module' object has no attribute 'RelatedObjectDoesNotExist'
AttributeError: 'module' object has no attribute 'RelatedObjectDoesNotExist'
>>>isinstance(foo, related.ReverseSingleRelatedObjectDescriptor.RelatedObjectDoesNotExist) Traceback (most recent call last): File "<string>", line 1, in <fragment> TypeError: isinstance() arg 2 must be a class, type, or tuple of classes and types
这可能就是为什么。
如果您的相关模型称为 Foo 您可以这样做:
except Foo.DoesNotExist:
当 Django 不可怕时,它就很棒。RelatedObjectDoesNotExist是一个属性,它返回在运行时动态计算出的类型。该类型self.field.rel.to.DoesNotExist用作基类。
RelatedObjectDoesNotExist
self.field.rel.to.DoesNotExist
根据 Django 文档:
不存在 异常 模型.DoesNotExist 当未找到预期对象时,ORM 会引发此异常。例如, QuerySet.get() 当没有为给定的查找找到对象时将引发它。 Django 提供了一个 DoesNotExist 异常作为每个模型类的属性来识别找不到的对象的类,允许您捕获特定模型类的异常。 例外是 的子类 django.core.exceptions.ObjectDoesNotExist 。
不存在
异常 模型.DoesNotExist
当未找到预期对象时,ORM 会引发此异常。例如, QuerySet.get() 当没有为给定的查找找到对象时将引发它。
QuerySet.get()
Django 提供了一个 DoesNotExist 异常作为每个模型类的属性来识别找不到的对象的类,允许您捕获特定模型类的异常。
DoesNotExist
例外是 的子类 django.core.exceptions.ObjectDoesNotExist 。
django.core.exceptions.ObjectDoesNotExist
这就是使这一切发生的魔力。一旦建立模型,self.field.rel.to.DoesNotExist该模型就不存在异常。