为什么 Django/Postgres 似乎保存但没有,给出 'connection already closed'?

Why does Django/Postgres appear to save but doesn't, gives 'connection already closed'?

我在 Windows 10 WSL Ubuntu 18.04.5 LTS 上使用 Django + Postgres。将数据保存到 postgres 似乎可行,但是当我在命令行上使用 psql 访问 table 时,数据不存在。刷新网页(重新加载 Django)也会显示保存前的旧数据。

postgresql 日志中没有错误。

我没有在 Django 的 settings.py 中显式打开缓存。

多年以来一切正常,但为了确保我将 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 异常。

我试过在 Django 设置中设置 CONN_MAX_AGE,没有什么不同,所以我删除了它。

在线搜索此错误仅提出了其他类型环境中的解决方案,通常是几年前的解决方案。

会不会是因为 Windows WSL2 的升级? google 搜索没有结果。

UPDATE:我刚刚注意到 apache 日志不见了(我在上面使用 'django runserver',而不是 apache,所以我没有注意到).自从我开始调试这个问题后,postgres 日志都是新的。我过去做过的 postgres sql 转储都不见了。幸运的是,我在 /var/www 中的源代码仍然存在。可能是 WSL 更新问题?

只要单元测试代码在进入测试中的断言检查之前出现错误,就会出现错误“psycopg2.InterfaceError:连接已关闭”。这本身不是 psycopg2 错误。至少可以说是一个不直观的信息。

我愿意接受有关如何在 Django 中进行单元测试的建议,在 Django 中会暴露此类错误,并在源代码中给出它们的位置,而不仅仅是在测试中 。我通过消除过程找到了它们:注释掉测试并使用 pdb.

单步执行代码

我的测试 类 都是 django.test.TestCase 的子类,因为它们在某些地方查询模型。来自 django unit testing docs:

If your tests rely on database access such as creating or querying models, be sure to create your test classes as subclasses of django.test.TestCase rather than unittest.TestCase.

Using unittest.TestCase avoids the cost of running each test in a transaction and flushing the database, but if your tests interact with the database their behavior will vary based on the order that the test runner executes them. This can lead to unit tests that pass when run in isolation but fail when run in a suite.