#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
sOneToOneField
не было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
notDoesNotExist
. Этот ответ совершенно не применим.2. Почему переопределение
.to_python()
таким образом, что оно вернет,None
если этого не происходитcollar
, неприменимо?