Ошибка Django — DoesNotExist — Как я могу сказать, чтобы разрешить это?

#django #django-models

#django #django-модели

Вопрос:

У меня есть две такие модели:

 class Collar(models.Model):
    num_tags = models.BigIntegerField()

class Dog(models.Model):
    num_legs = models.BigIntegerField()
    collar =  models.OneToOneField(Collar,null=True,blank=True)
  

Всякий раз, когда я пытаюсь сделать что-то вроде:

 dog = Dog.objects.all()[0]
if dog.collar:
    #do something ...
  

Я получаю ошибку DoesNotExist в строке: если dog.collar.

Как я могу сказать Django, что это нормально? Что ошейник не всегда будет существовать, и я хочу проверить его существование, не вызывая ошибки?

Комментарии:

1. Вы изменили свою модель с тех пор, как таблицы были созданы с помощью syncdb ?

2. Да! Вероятно, для моделей еще не создана таблица…

3. Пожалуйста, разместите отладочные данные здесь. Итак, решить вашу проблему будет действительно легко 😉

4. @Jayme: Я подозреваю, что у Dog.collar s OneToOneField не было null=True опции при создании таблицы, а не то, что таблица не существовала.

5. Я пытался создать игрушечный пример, чтобы проиллюстрировать проблему, мои реальные модели занимают много страниц, и мне удалось установить значение False. Поскольку похоже, что мое понимание того, как работают модели, кажется правильным, где-то должна быть ошибка или проблема с синхронизацией. Я начну искать это. Спасибо

Ответ №1:

Используйте try..except блок:

 try:
   if dog.collar:
       # Do something
except Collar.DoesNotExist:
   # Do something else
  

Кроме того, никогда не предполагайте, что all() всегда будет возвращать что-то. В идеальных обстоятельствах, конечно, но жизнь никогда не бывает идеальной. Вам нужно использовать потенциал IndexError с помощью такого заявления и иметь план действий на случай непредвиденных обстоятельств:

 try:
    dog = Dog.ojbects.all()[0]
except IndexError:
    # Contingency plan so website doesn't explode
  

Комментарии:

1. Это правильный ответ на вопрос, поэтому 1. Однако это неправильный вопрос. У вас не должно быть идентификатора для collar, если collar не существует. Операционные данные повреждены, и в этом проблема. Я бы проверил правила ondelete.

Ответ №2:

Я подозреваю, что определение вашей модели изменилось с тех пор, как вы впервые создали свои таблицы с помощью manage.py syncdb .

Ваша первоначальная Dog модель, вероятно, выглядела как:

 class Dog(models.Model):
    num_legs = models.BigIntegerField()
    collar =  models.OneToOneField(Collar)
  

Затем вы создали свои таблицы с помощью manage.py syncdb , которая создала таблицы модели Dog и Collar .

Наконец, вы решили, что Dog.collar должно быть необязательным разрешать такие конструкции, как:

 dog = Dog.ojbects.all()[0]
if dog.collar:
    #do something ...
  

и изменил вашу модель на:

 class Dog(models.Model):
    num_legs = models.BigIntegerField()
    collar =  models.OneToOneField(Collar,null=True,blank=True)
  

затем обновил ваши модели с помощью manage.py syncdb и столкнулся с классической ошибкой Django из-за неправильно введенной команды: syncdb команда не синхронизирует таблицы с определениями моделей, она создает таблицы.

Я подозреваю, что если вы удалите таблицы, связанные с Dog и запустите syncdb повторно, ваш сокращенный код начнет работать.

Ответ №3:

Вы проверили это?

 if getattr(dog, collar):
  

И один из возможных способов — вывод из OneToOneField с переопределением .to_python() путем добавления блока try / except.

Комментарии:

1. Давайте, ребята. Если бы это было так, ошибка была бы AttributeError not DoesNotExist . Этот ответ совершенно не применим.

2. Почему переопределение .to_python() таким образом, что оно вернет, None если этого не происходит collar , неприменимо?