Django перевіряє, чи існує пов’язаний об’єкт, помилка: RelatedObjectDoesNotExist


78

У has_related_objectмоїй моделі є метод, який потрібно перевірити, чи існує пов’язаний об’єкт

class Business(base):
      name =  models.CharField(max_length=100, blank=True, null=True)

  def has_related_object(self):
        return (self.customers is not None) and (self.car is not None)


class Customer(base):
      name =  models.CharField(max_length=100, blank=True, null=True)
      person = models.OneToOneField('Business', related_name="customer")

Але я отримую помилку:

Business.has_related_object ()

RelatedObjectDoesNotExist: Бізнес не має замовника.


1
Я не можу повірити, що Django не забезпечує цей метод.
— etlds

Відповіді:


76

Це тому, що ORM повинен перейти до бази даних, щоб перевірити, чи customerіснує. Оскільки він не існує, він створює виняток.

Вам доведеться змінити метод на такий:

def has_related_object(self):
    has_customer = False
    try:
        has_customer = (self.customers is not None)
    except Customer.DoesNotExist:
        pass
    return has_customer and (self.car is not None)

Я не знаю ситуацію з, self.carтому я залишу вас, щоб ви це налаштували, якщо це потрібно.

Примітка: Якщо ви робили це на пристрої, Modelякий має ForeignKeyFieldабо OneToOneFieldна ньому, ви могли б зробити наступне як ярлик, щоб уникнути запиту до бази даних.

def has_business(self):
    return self.business_id is not None

1
Зверніть увагу, що відповідно до документа ( docs.djangoproject.com/en/1.9/ref/models/fields/… ), "[...] ваш код ніколи не повинен мати справу з іменем стовпця бази даних, якщо ви не пишете власний SQL Ви завжди будете мати справу з іменами полів вашого об'єкта моделі. "
— Антуан Пінсар

Цей підхід швидший за іншу відповідь, оскільки не вимагає спілкування з базою даних.
— Ден,

4
@AntoinePinsard, використання імені стовпця в цьому випадку швидше, оскільки Django не намагатиметься об’єднатись у базовому запиті. Django заохочує ці практики для необхідних оптимізацій. docs.djangoproject.com/en/2.1/topics/db/optimization/…
— Bobort

1
Чому Django просто не повертається, Noneякщо ви намагаєтесь запитати об’єкт щодо одного з його зв’язків? Викидання винятку здається надмірним.
— mecampbellsoup

2
Ймовірно, це зроблено, щоб охопити випадок наявності поля, що допускає обнулення. Коли дозволено мати значення null, він повертає None. Коли це не так, тоді виникає виняток.
— schillingt

154

Використовуйте, hasattr(self, 'customers')щоб уникнути перевірки винятків, як рекомендується в документах Django :

def has_related_object(self):
    return hasattr(self, 'customers') and self.car is not None

4
Взагалі кажучи на python це EAFP. docs.python.org/3/glossary.html#term-eafp
— Дастін Вайатт

5
За винятком того, що запитувати дозвіл у цьому випадку однаково просто, і включати все, що намагається: крок речей, як правило, маскує непов’язані помилки, ускладнюючи налагодження проблем.
— kloddant
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.