你如何看待这个例外?

这段代码在django / db / models / fields.py中它创build/定义了一个exception?

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 /数据库/模型/领域/ related.py它引发了上述exception:

 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 

isinstance(foo,related.FieldDoesNotExist)除了Exception之外的错误,因为foo:print type(foo)#在这里捕获,不在上面

将不会捕捉到这个例外

 >>>print type(foo) <class 'django.db.models.fields.related.RelatedObjectDoesNotExist'> 

 except related.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不可怕的时候,Django是惊人的。 RelatedObjectDoesNotExist是返回在运行时dynamic计算的types的属性。 该types使用self.field.rel.to.DoesNotExist作为基类。 根据Django文档:

ObjectDoesNotExist和DoesNotExist

exceptionDoesNotExist

如果查询的给定参数找不到对象,则会引发DoesNotExistexception。 Django提供了一个DoesNotExistexception作为每个模型类的一个属性来标识无法find的对象的类,并允许你用try / except来捕获一个特定的模型类。

这是发生这种事情的魔法。 一旦模型build立起来, self.field.rel.to.DoesNotExist就是该模型不存在的exception。

如果您不想导入相关的模型类,您可以:

 except MyModel.related_field.RelatedObjectDoesNotExist: 

要么

 except my_model_instance._meta.model.related_field.RelatedObjectDoesNotExist: 

其中related_field是字段名称。

一般来说,要抓住这个例外,你可以这样做

 from django.core.exceptions import ObjectDoesNotExist try: # Your code here except ObjectDoesNotExist: # Handle exception