आप इस अपवाद को कैसे पकड़ते हैं?


162

यह कोड django / db / मॉडल / field.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 / मॉडल / फ़ील्ड / संबंधित Oracle में है, जो उपरोक्त अपवाद को उठाता है:

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:

उठाता है a 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

जो शायद है।


आपने कैसे आयात किया है related?
जॉन Zwinck

4
AttributeErrorइसके बजाय का उपयोग करेंrelated.ReverseSingleRelatedObjectDescriptor.RelatedObjectDoesNotExist
कैथरीन

हां @ जॉन्ज्विनक मैंने संबंधित आयात किया है।
बोटकोडर

जवाबों:


302

यदि आपके संबंधित मॉडल को फू कहा जाता है, तो आप कर सकते हैं:

except Foo.DoesNotExist:

Django अद्भुत है जब इसके भयानक नहीं है। RelatedObjectDoesNotExistएक संपत्ति है जो एक प्रकार का रिटर्न देता है जिसे रनटाइम पर गतिशील रूप से खोजा जाता है। वह प्रकार self.field.rel.to.DoesNotExistआधार वर्ग के रूप में उपयोग होता है । Django प्रलेखन के अनुसार:

ObjectDoesNotExist और doesNotExist

अपवाद DoNotExist

DoesNotExist अपवाद उठाया एक वस्तु एक प्रश्न के दिए गए मापदंडों के लिए नहीं मिला है जब है। Django ऑब्जेक्ट के वर्ग की पहचान करने के लिए प्रत्येक मॉडल वर्ग की विशेषता के रूप में एक DoNotExist अपवाद प्रदान करता है जो कि नहीं पाया जा सकता है और आपको try/ केexcept साथ एक विशेष मॉडल वर्ग को पकड़ने की अनुमति देता है ।

यह जादू है जो ऐसा करता है। एक बार मॉडल का निर्माण हो जाने के बाद, self.field.rel.to.DoesNotExistउस मॉडल के लिए मौजूद नहीं अपवाद है।


7
क्योंकि बग DjangoRestFramework में था, और मॉडल उस बिंदु पर आने के लिए कुछ हद तक कठिन है। मैं ObjectDoesNotExist को पकड़ने के लिए तय हुआ।
नाविक

3
आप एट्रीब्यूटर का उपयोग भी कर सकते हैं, जो कुछ परिस्थितियों में एक बेहतर विकल्प हो सकता है (यह त्रुटि लगभग हमेशा तब होती है जब आप किसी रिकॉर्ड की "विशेषता" तक पहुंच रहे हैं, इसलिए इस तरह से आपको ट्रैक रखने की ज़रूरत नहीं है कि क्या यह विशेषता एक से मेल खाती है रिकॉर्ड या नहीं।
जॉर्डन रीटर

1
याया ठीक है। लेकिन यह सिर्फ कोई नहीं लौटा सकता है? खासकर एक-से-एक खेतों के साथ। या कोई अच्छा कारण है?
नील

61

यदि आप संबंधित मॉडल वर्ग का आयात नहीं करना चाहते हैं, तो आप कर सकते हैं:

except MyModel.related_field.RelatedObjectDoesNotExist:

या

except my_model_instance._meta.model.related_field.RelatedObjectDoesNotExist:

related_fieldक्षेत्र का नाम कहां है


7
यदि आप परिपत्र आयात से बचना चाहते हैं तो यह वास्तव में बहुत उपयोगी है। साभार
गियोवन्नी डि मिलिया

40

सामान्य रूप से इस अपवाद को पकड़ने के लिए, आप कर सकते हैं

from django.core.exceptions import ObjectDoesNotExist

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

2
मैंने पाया कि यह वास्तव में अपेक्षा के अनुरूप त्रुटि नहीं पकड़ पाया। <Model>.DoesNotExistकिया था
एरिक ब्लम

1
@EricBlum <मॉडल> ​​.DoesNotExist ObjectDoesNotExist का वंशज है, इसलिए ऐसा नहीं होना चाहिए। क्या आप इस बारे में खुदाई कर सकते हैं कि ऐसा क्यों हो रहा है या अपने कोड के बारे में अधिक जानकारी दें?
ज़ैग्स

10

RelatedObjectDoesNotExistअपवाद कार्यावधि में गतिशील रूप से बनाई गई है। यहाँ ForwardManyToOneDescriptorऔर ReverseOneToOneDescriptorविवरण के लिए प्रासंगिक कोड स्निपेट दिया गया है :

@cached_property
def RelatedObjectDoesNotExist(self):
    # The exception can't be created at initialization time since the
    # related model might not be resolved yet; `self.field.model` might
    # still be a string model reference.
    return type(
        'RelatedObjectDoesNotExist',
        (self.field.remote_field.model.DoesNotExist, AttributeError),
        {}
    )

तो अपवाद <model name>.DoesNotExistऔर से विरासत में मिला AttributeError। वास्तव में, इस अपवाद प्रकार के लिए पूरा MRO है:

[<class 'django.db.models.fields.related_descriptors.RelatedObjectDoesNotExist'>, 
<class '<model module path>.DoesNotExist'>,
<class 'django.core.exceptions.ObjectDoesNotExist'>,
<class 'AttributeError'>,
<class 'Exception'>,
<class 'BaseException'>,
<class 'object'>]

मूल takeaway आप पकड़ सकते हैं <model name>.DoesNotExist, ObjectDoesNotExist(से आयात django.core.exceptions) या AttributeError, जो भी आपके संदर्भ में सबसे अधिक समझ में आता है।


2

नियमित कोड पथ के लिए tdelaney का उत्तर बहुत अच्छा है, लेकिन अगर आपको यह जानना है कि परीक्षणों में इस अपवाद को कैसे पकड़ा जाए:

from django.core.exceptions import ObjectDoesNotExist

...

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

2

थोड़ा देर से लेकिन दूसरों के लिए मददगार।

इससे निपटने के 2 तरीके।

पहला:

जब हमें अपवाद को पकड़ने की जरूरत है

>>> from django.core.exceptions import ObjectDoesNotExist
>>> try:
>>>     p2.restaurant
>>> except ObjectDoesNotExist:
>>>     print("There is no restaurant here.")
There is no restaurant here.

दूसरा: जब अपवाद को संभालना नहीं है

>>> hasattr(p2, 'restaurant')
False
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.