Почему Django/Postgres вроде бы сохраняет, но не сохраняет, выдает "соединение уже закрыто"?
Я использую Django + Postgres на Windows 10 WSL Ubuntu 18.04.5 LTS. Сохранение данных в postgres вроде бы работает, но когда я обращаюсь к таблице с помощью psql в командной строке, данных там нет. Обновление веб-страницы (перезагрузка Django) также показывает старые данные, предшествующие сохранению.
В журнале postgresql нет ошибок.
У меня нет явного включения кэширования в файле settings.py.
в Django.Все это прекрасно работало в течение многих лет, но для уверенности я обновил Django до 3.2.6, Python до 3.8.11, postgresql до 12, и psycopg2 до 2.9.1, плюс необходимые зависимости. Результат тот же.
Вот код на Django:
try:
nodeToUpdate.save() # Hit the database.
node = Node.objects.get(pk=itemID, ofmap=mapId) # Retrieve again to confirm it was saved
# This shows the correct data:
print("STORE TO MAP:" + str(node.ofmap_id) + " NODE:" + str(node.id) + " label:" + str(node.label))
except psycopg2.InterfaceError as err:
print(str(err))
raise Exception(err)
except ValidationError as err:
raise Exception(err)
Разгадка того, что происходит, приходит, когда я запускаю модульные тесты:
Traceback (most recent call last):
File "/var/www/mysite/venv/lib/python3.8/site-packages/django/db/backends/base/base.py", line 237, in _cursor
return self._prepare_cursor(self.create_cursor(name))
File "/var/www/mysite/venv/lib/python3.8/site-packages/django/utils/asyncio.py", line 26, in inner
return func(*args, **kwargs)
File "/var/www/mysite/venv/lib/python3.8/site-packages/django/db/backends/postgresql/base.py", line 236, in create_cursor
cursor = self.connection.cursor()
**psycopg2.InterfaceError: connection already closed**
Но это исключение InterfaceError не поймано в коде, который я показал выше.
Я попробовал установить CONN_MAX_AGE в настройках Django, ничего не изменилось, поэтому я удалил его.
Поиски этой ошибки в Интернете привели только к решениям в других типах сред, обычно несколько лет назад.
Может ли это быть связано с обновлением WSL2 в Windows? В поиске Google ничего не нашлось.
UPDATE: Я только что заметил, что журналы apache исчезли (я использую 'django runserver' для этого, вместо apache, поэтому я не заметил). Журналы postgres все новые с тех пор, как я начал отлаживать эту проблему. Дампы sql postgres, которые я делал в прошлом, исчезли. К счастью, мой исходный код в /var/www остался. Возможно, это проблема обновления WSL?
Ошибка "psycopg2.InterfaceError: connection already closed" появляется всякий раз, когда в тестируемом коде возникает ошибка до того, как он дойдет до проверки утверждений в тесте. Это не ошибка psycopg2, как таковая. Неинтуитивное сообщение, мягко говоря.
Я открыт для предложений о том, как сделать модульное тестирование в Django, при котором такие ошибки будут выявлены и их местоположение указано в исходном коде, а не только в тестах. Я находил их методом исключения: комментируя тесты и проходя по коду с помощью pdb.
Все мои тестовые классы подклассифицированы из django.test.TestCase, поскольку они местами запрашивают Models. Из документации django unit testing docs:
Если ваши тесты используют доступ к базе данных, например, создание или запрос модели, обязательно создавайте свои тестовые классы как подклассы django.test.TestCase, а не unittest.TestCase.
.Использование unittest.TestCase позволяет избежать затрат на запуск каждого теста в транзакции и промывки базы данных, но если ваши тесты взаимодействуют с базой данных, их поведение будет меняться в зависимости от порядка, в котором тест runner выполняет их. Это может привести к тому, что модульные тесты будут успешными при выполнении изолированно, но проваливаются при запуске в наборе.