Как правильно проверить, существует ли объект в представлении django, не возвращая 404?

93

Мне нужно проверить, существует ли объект, и вернуть объект, а затем на основе этого выполнить действия. Как правильно это сделать, не возвращая 404?

try:
    listing = RealEstateListing.objects.get(slug_url = slug)
except:
    listing = None

if listing:
Расиэль
источник
Расиэль, могу я предложить вам рассмотреть возможность принятия другого ответа? Кажется, это правильный способ сделать это, и он получил немного больше голосов, чем принятый ответ.
Azendale
1
Я могу считать это, однако он существует, был введен в Django 1.2, который был выпущен 17 мая 2010 г. Если вы заметили, что мой вопрос был отправлен в 09 ... это был правильный ответ в то время. Если Exists () теперь считается лучшим способом сделать это, я думаю, было бы семантически правильно выбрать второй ответ, верно?
Rasiel
Расиэль, логично, что это был правильный ответ в то время. Но сайты stackoverflow, похоже, столько же посвящены созданию набора хороших / официальных вопросов с лучшими ответами, сколько и сайты находят решения для проблем людей. Поэтому я предлагаю выбрать то, что сейчас является «официально правильным» ответом.
Azendale
if listing:Должно быть else:.
Chronial,

Ответы:

117

Я бы не стал использовать обертку 404, если вам не дадут 404. Это злоупотребление намерением. Вместо этого просто поймайте DoesNotExist.

try:
    listing = RealEstateListing.objects.get(slug_url=slug)
except RealEstateListing.DoesNotExist:
    listing = None
железный лягушонок
источник
+1: Да, это лучшее решение, чем принятое, если вам не нужен 404.
Карл Мейер,
yap
3
Это решение работает лучше, чем exists()если вам нужно что-то делать с объектом.
SaeX
2
Хочу добавить values_list('id', flat=True). если мне нужно просто посмотреть, существует лиlisting = RealEstateListing.objects.values_list('id', flat=True).get(slug_url=slug)
эраджуан
Что мне кажется странным в этом синтаксисе, так это то, что RealEstateListing.DoesNotExistон относится к модели, а не к самому объекту. Почему нет RealEstateListing.objects.get(slug_url=slug).DoesNotExist?
Максим Валле,
200

Вы также можете:

if not RealEstateListing.objects.filter(slug_url=slug).exists():
    # do stuff...

Иногда проще использовать try: except:блок, а иногда однострочный exists()код делает код более понятным ... все зависит от логики вашего приложения.

Zzart
источник
8
.exists () быстрее: docs.djangoproject.com/en/dev/ref/models/querysets/#exists
fjsj 04
7
это лучший способ и должен иметь ответ
Джарвуд
3
Я предполагаю, что exists()это не работает get(), верно?
Эдуард Лука
9
Обратите внимание, что это решение действительно только в том случае, если вы не собираетесь использовать рассматриваемый объект. В противном случае (как в случае с OP) это неправильно и намного медленнее, чем принятое решение: если вы сделаете это get()позже, он отправит второй запрос в базу данных.
Chronial
1
Если вы проверяете существование , чтобы сделать что - то с объектом (если она существует), то я предпочитаю try-exceptболее exists().
Джитин Павитран
7
listing = RealEstateListing.objects.filter(slug_url=slug).first() 
Хенрик Хейно
источник
2
Это лучшее решение, если вам нужно использовать потенциальный объект позже, поскольку для этого требуется только одно назначение, и это позволяет избежать использования блока try / except. Обратите внимание, что вы можете проверить существование позже просто сif listing:
Майкл Хейс
Избегать попытки / кроме - плохая практика. Одним из наиболее важных аспектов разработки программного обеспечения является возможность управления исключениями, чтобы обеспечить удобство работы пользователей. Сообщите людям, когда что-то не работает должным образом. Второй; если вы хотите проверить наличие QuerySet, используйте .exists (), иначе это объект. Проверить существование с их первичным ключом .... if object.pk: // run code () Этот запрос выполняется намного быстрее, чем получение всех данных объекта. Вы просто хотите знать, существует ли.
Вольфганг Леон
2
Уже были решения с использованием try / except и .exists(). Я думаю, что в SO есть несколько разных ответов, как что-то делать. Может быть, это лучше для тех, кто тоже хочет использовать объект, если он существует. Я бы не стал устанавливать никаких правил, если пытаться / кроме того, следует избегать или нет. Иногда это хорошо, а иногда плохо, например, если вы просто хотите сделать очень компактный код.
Хенрик Хейно
0

Я бы сделал это так просто:

listing = RealEstateListing.objects.filter(slug_url=slug)
if listing:
    # do stuff

Я не вижу необходимости пытаться / поймать. Если в результате потенциально есть несколько объектов, используйте first (), как показано пользователем Хенриком Хейно.

Грег Холст
источник
Если вы не выполните .first () в наборе запросов или .first () в условном выражении, это всегда будет возвращать True.
Б. Адлер,