Как вы поймаете это исключение?

Этот код находится в 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

isinstance (foo, related.FieldDoesNotExist) Ложь       кроме Exception как foo:           Тип печати (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

вероятно, поэтому.

Ответ 1

Если ваша родственная модель называется Foo, вы можете просто сделать:

except Foo.DoesNotExist:

Джанго поражает, когда его не страшно. RelatedObjectDoesNotExist - это свойство, которое возвращает тип, который динамически вычисляется во время выполнения. Этот тип использует self.field.rel.to.DoesNotExist как базовый класс. Согласно документации Django:

ObjectDoesNotExist и DoNotExist

исключение DoesNotExist

Исключение DoNotExist возникает, когда объект не найден для заданные параметры запроса. Django предоставляет DoNotExistисключение как атрибут каждого класса модели для определения класса объект, который не может быть найден, и чтобы вы могли поймать конкретную класс модели с try/except.

Это волшебство, которое заставляет это случиться. После того, как модель была построена, self.field.rel.to.DoesNotExist - исключение does-not-exist для этой модели.

Ответ 2

Если вы не хотите импортировать соответствующий класс модели, вы можете:

except MyModel.related_field.RelatedObjectDoesNotExist:

или

except my_model_instance._meta.model.related_field.RelatedObjectDoesNotExist:

где related_field - имя поля.

Ответ 3

Чтобы поймать это исключение в целом, вы можете сделать

from django.core.exceptions import ObjectDoesNotExist

try:
    # Your code here
except ObjectDoesNotExist:
    # Handle exception

Ответ 4

Ответ tdelaney отлично подходит для обычных кодов кода, но если вам нужно знать, как поймать это исключение в тестах:

from django.core.exceptions import ObjectDoesNotExist

...

    def testCompanyRequired(self):
        with self.assertRaises(ObjectDoesNotExist):
            employee = Employee.objects.create()