Ce code est dans django / db / models / fields.py Il crée / définit une 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),
{}
)
C'est dans django / db / models / fields / related.py cela lève l'exception ci-dessus:
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
Le problème est que ce code:
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
n'attrapera pas cette exception
>>>print type(foo)
<class 'django.db.models.fields.related.RelatedObjectDoesNotExist'>
>>>isinstance(foo, related.FieldDoesNotExist)
False
et
except related.RelatedObjectDoesNotExist:
Lève 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
c'est probablement pourquoi.
related
?AttributeError
place derelated.ReverseSingleRelatedObjectDescriptor.RelatedObjectDoesNotExist
Réponses:
Si votre modèle associé s'appelle Foo, vous pouvez simplement faire:
Django est incroyable quand ce n'est pas terrifiant.
RelatedObjectDoesNotExist
est une propriété qui renvoie un type qui est déterminé dynamiquement à l'exécution. Ce type utiliseself.field.rel.to.DoesNotExist
comme classe de base. Selon la documentation Django:C'est la magie qui fait que cela se produit. Une fois que le modèle a été construit,
self.field.rel.to.DoesNotExist
est l'exception n'existe pas pour ce modèle.la source
Si vous ne souhaitez pas importer la classe de modèle associée, vous pouvez:
ou
où
related_field
est le nom du champ.la source
Pour intercepter cette exception en général, vous pouvez faire
la source
<Model>.DoesNotExist
didL'
RelatedObjectDoesNotExist
exception est créée dynamiquement lors de l'exécution. Voici l'extrait de code pertinent pour les descripteursForwardManyToOneDescriptor
etReverseOneToOneDescriptor
:Ainsi, l'exception hérite de
<model name>.DoesNotExist
etAttributeError
. En fait, le MRO complet pour ce type d'exception est:La chose à retenir est que vous pouvez capturer
<model name>.DoesNotExist
,ObjectDoesNotExist
(importer depuisdjango.core.exceptions
) ouAttributeError
tout ce qui a le plus de sens dans votre contexte.la source
Un peu tard mais utile pour les autres.
2 façons de gérer cela.
1er:
Quand nous devons attraper une exception
2ème: Quand je ne veux pas gérer l'exception
la source
La réponse de tdelaney est idéale pour les chemins de code normaux, mais si vous avez besoin de savoir comment intercepter cette exception dans les tests:
la source