Ошибка Django - соответствующий запрос не существует

92

Я наконец выпустил свой проект на производственный уровень, и внезапно у меня возникли проблемы, с которыми мне никогда не приходилось сталкиваться на этапе разработки.

Когда пользователи публикуют какие-то действия, я иногда получаю следующую ошибку.

Traceback (most recent call last):

  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)

  File "home/ubuntu/server/opineer/comments/views.py", line 103, in comment_expand
    comment = Comment.objects.get(pk=comment_id)

  File "/usr/local/lib/python2.7/dist-packages/django/db/models/manager.py", line 131, in get
    return self.get_query_set().get(*args, **kwargs)

  File "/usr/local/lib/python2.7/dist-packages/django/db/models/query.py", line 366, in get
    % self.model._meta.object_name)

DoesNotExist: Comment matching query does not exist

Что меня действительно расстраивает, так это то, что проект отлично работает в локальной среде и, кроме того, соответствующий объект запроса ДЕЙСТВИТЕЛЬНО существует в базе данных.

Теперь я подозреваю, что пользователь получает доступ к базе данных, когда она зарезервирована для других пользователей, но нет способа доказать мой аргумент, и у меня нет никакого решения для него.

У кого-нибудь раньше была такая проблема? Есть предложения по решению этой проблемы?

Заранее большое спасибо за вашу помощь.

РЕДАКТИРОВАТЬ: я вручную запросил базу данных, используя ту же информацию, что и полученное мной сообщение об ошибке сервера. Я смог попасть в запись без каких-либо проблем. Более того, похоже, что точно такое же поведение, которое совершил пользователь, большую часть времени не вызывает никаких проблем, а скорее в некоторых (что пока неизвестно) случаях. В заключение, это определенно не проблема с отсутствующей записью в базе данных.

Крис П.
источник
2
Ясно, что это проблема с данными: comment = Comment.objects.get(pk=comment_id)убедитесь, что идентификатор существует в базе данных
karthikr
3
"python manage.py sqlall" сгенерирует SQL, соответствующий вашим моделям. Проверить, соответствует ли он схеме БД SQL. Например, при работе с PostgreSQL это также может быть проблемой последовательности. В заключение: можете ли вы предоставить дополнительную информацию о своей среде (SQDB, DB, соответствующая таблица в DB и код в models.py, ...)?
Ricola3D
@ Ricola3D Здравствуйте, Ricola, в настоящее время я использую MySql DB, размещающую его из экземпляра Amazon EC2. И я пока использую встроенный в Django Comment. А пока я попробую запустить предложенную вами команду sqlall. Спасибо.
Chris P

Ответы:

97

ваша строка, вызывающая ошибку, находится здесь:

comment = Comment.objects.get(pk=comment_id)

вы пытаетесь получить доступ к несуществующему комментарию.

from django.shortcuts import get_object_or_404

comment = get_object_or_404(Comment, pk=comment_id)

Вместо того, чтобы иметь ошибку на вашем сервере, ваш пользователь получит 404, что означает, что он пытается получить доступ к несуществующему ресурсу.

Хорошо, я полагаю, вы знаете об этом.

Некоторые пользователи (и я их часть) позволяют вкладкам работать долгое время, если пользователям разрешено удалять данные, это может произойти. Ошибка 404 может быть лучшей ошибкой для обработки ошибки удаленного ресурса, чем отправка электронного письма администратору.

Другие пользователи переходят по адресам из своей истории (то же самое, если данные были удалены, поскольку это может произойти).

Кристоф31
источник
3
+1 на долго работающих вкладках. 404 через старые вкладки случается со мной очень часто.
Yuji 'Tomita' Tomita
Спасибо, Крис, за ваше предложение. Что меня действительно беспокоит, так это то, что когда я запрашиваю базу данных MySql вручную (используя информацию об ошибке, которую я получил с сервера), я без проблем нажимаю правильную запись. Кроме того, одно и то же действие иногда вызывает исключение DoesNotExist, но работает в большинстве случаев. Это не похоже на проблему с отсутствующей записью в базе данных :(
Крис П.
У меня может быть меньше пользователей, но с postgres у меня никогда не было таких проблем. У нас действительно мало информации, в вашей базе данных нет ведомой / ведущей кластеризации? Вы не используете кеш в наборах запросов?
christophe31
@ christophe31 Итак, я еще не реализовал какую-либо оптимизацию производительности БД или методы резервного копирования, такие как кластеризация ведомого / ведущего устройства или кеширование в наборах запросов. Думаю, я внедрю эти функции и посмотрю, сохраняется ли проблема.
Chris P
2
Также вы можете добавить это в улове: from django.db import connection, connection.connection.close(), connection.connection = Noneчтобы попытаться сбросить дб соединение и начать с новой.
christophe31
106

Возможно, у вас нет записи Комментариев с таким первичным ключом, тогда вам следует использовать этот код:

try:
    comment = Comment.objects.get(pk=comment_id)
except Comment.DoesNotExist:
    comment = None
Драконтис
источник
3
Лучший вариант в таких случаях. Вместо того, чтобы бросать 404 пользователю, перехватите ошибку и отобразите красивое предварительно настроенное сообщение. Сердце не горит.
user12379095
Как это будет работать здесь? def previous_job(self): return self.get_previous_by_start_dt(brand=self.brand, status='finished') or Noneне знаю, как реализовать здесь try catch
snh_nl
22

Вы можете использовать это:

comment = Comment.objects.filter(pk=comment_id)
Кланг Вутчарин
источник
Что ж, если есть конкретный объект, который вам нужен, вы не можете использовать фильтр, так как он может вернуть пустой список, если запрос не соответствует. И когда он совпадает, вы должны использовать первый объект из списка.
Джей Моди
3
Предположительно, в этом суть: использовать фильтр и проверить, содержит ли результат ноль или одну запись, вместо генерации исключения?
Майк 'Pomax' Камерманс
Стоит отметить, что Model.objects.filterвернет Queryset, тогда как Model.objects.getвернет объект. Если объект не существует, первый вернет пустой запрос, второй вызовет Model.DoesNotExistошибку.
ron_g
Comment.objects.filter(pk=comment_id).first()вернется, Noneесли записи не найдены.
steezeburger
12

Вы можете попробовать этот способ. просто используйте функцию, чтобы получить свой объект

def get_object(self, id):
    try:
        return Comment.objects.get(pk=id)
    except Comment.DoesNotExist:
        return False
Мехеди Хасан
источник