Este código está en django / db / models / fields.py ¿Crea / define una excepción?
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),
{}
)
Esto está en django / db / models / fields / related.py plantea la excepción mencionada anteriormente:
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
El problema es que este código:
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
no atrapará esa excepción
>>>print type(foo)
<class 'django.db.models.fields.related.RelatedObjectDoesNotExist'>
>>>isinstance(foo, related.FieldDoesNotExist)
False
y
except related.RelatedObjectDoesNotExist:
Plantea un 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
probablemente por eso
related
?AttributeError
lugar derelated.ReverseSingleRelatedObjectDescriptor.RelatedObjectDoesNotExist
Respuestas:
Si su modelo relacionado se llama Foo, simplemente puede hacer:
Django es increíble cuando no es aterrador.
RelatedObjectDoesNotExist
es una propiedad que devuelve un tipo que se calcula dinámicamente en tiempo de ejecución. Ese tipo se usaself.field.rel.to.DoesNotExist
como una clase base. De acuerdo con la documentación de Django:Esta es la magia que hace que eso suceda. Una vez que el modelo ha sido construido,
self.field.rel.to.DoesNotExist
es la excepción de no existir para ese modelo.fuente
Si no desea importar la clase de modelo relacionada, puede:
o
donde
related_field
está el nombre del campofuente
Para atrapar esta excepción en general, puede hacer
fuente
<Model>.DoesNotExist
hizoLa
RelatedObjectDoesNotExist
excepción se crea dinámicamente en tiempo de ejecución. Aquí está el fragmento de código relevante para los descriptoresForwardManyToOneDescriptor
yReverseOneToOneDescriptor
:Entonces la excepción hereda de
<model name>.DoesNotExist
yAttributeError
. De hecho, el MRO completo para este tipo de excepción es:La conclusión básica es que puedes atrapar
<model name>.DoesNotExist
,ObjectDoesNotExist
(importar desdedjango.core.exceptions
) oAttributeError
, lo que tenga más sentido en tu contexto.fuente
La respuesta de tdelaney es excelente para rutas de código normales, pero si necesita saber cómo detectar esta excepción en las pruebas:
fuente
Un poco tarde pero útil para los demás.
2 formas de manejar esto.
1er:
Cuando necesitamos atrapar excepciones
2do: Cuando no quiere manejar una excepción
fuente