Dockerized Django 应用程序未应用唯一约束

Dockerized Django app not applying unique constraint

我有两个相互关联的问题

第 1 期

我的应用程序有一个用于存储数据的在线 Postgres 数据库。因为这是一个 Docker 化的应用程序,所以我创建的迁移不再出现在我的本地主机上,而是存储在 Docker 容器中。 到目前为止我看到的所有问题似乎都没有关于进行迁移和将唯一约束添加到 table 中的字段之一的问题。

我已经将 shell 代码编写到 运行 一个 python 脚本,returns 我在命令提示符 window 中获取迁移文件的内容。我能够获得要应用的迁移文件,并在 django_migrations table 中添加一行以指定相同的内容。然后我 运行 makemigrations and migrate 但它说没有应用任何更改(这让我相信我添加到数据库中的行应该只由 django 在它自己检测到迁移之后自动创建我指定迁移文件并要求它进行更改)。问题是现在,新的迁移仍然检测到以下变化

Migrations for 'mdp':
  db4mdp/mdp/migrations/0012_testing.py
    - Alter field mdp_name on languages

尽管检测到这个明显的 'change',但我收到以下错误,

return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "mdp_mdp_mdp_fullname_281e4228_uniq" already exists

我已经使用 pgadmin4 检查了我的 postgres 服务器,以检查是否实际应用了约束。并且它具有上面指定的关系旁边的名称。那么,为什么 Django 显然会将此检测为要进行的更改。问题是,如果我现在删除我在 python 目录中创建的新迁移文件,它可能会 运行 (因为数据库中已经进行了 'apparently' 更改)但是我不会有迁移文件来跟踪更改。不过,既然我正在使用在线数据库,我就不需要保留迁移了。我不会回滚我所做的任何更改,也不会经常进行更改。这只是 one/two 时间问题,但我想解决错误。

第 2 期

我在上面的问题中使用 'apparently' 的原因是,尽管我的 public 模式中的约束部分显示我已经应用了约束,但出于某种原因,当我尝试在我定义为唯一的字段中使用非唯一字符串在我的 table 中创建一个新条目,无论如何它都允许创建。

您永远不会手动向 django_migrations table 添加任何内容。让 django 来做。如果它没有这样做,无论如何,您的代码都没有准备好生产。 我了解到您正在 docker 内部进行开发。执行此操作时,您将 docker 卷挂载到本地卷。由于您尚未安装它,因此您的 migratins 不会在本地显示。 参考 Volumes。它应该可以解决您的问题。

对于任何试图找到替代解决方案的人来说,除了由于时间限制安装卷之外,这个答案可能会有所帮助,但@deosha 的仍然是解决这个问题的正确方法。我通过删除我的所有 tables 和与迁移到我的特定应用程序对应的行解决了这个问题(没有必要删除 auth tables 等,因为你不会删除对应于 django_migrations table 中的行)。在此之后,我在我的 Dockerfile 调用的 shell 脚本中使用了以下内容。

python manage.py makemigrations --name testing
python testing_migrations.py

下一步需要命名。在这行代码之后,我 运行 python 脚本 testing_migrations 其中包含以下代码:

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
migrations_file = os.path.join(BASE_DIR, '<path_to_new_migration_file>')
with open(migrations_file, 'r') as file:
    print(file.read())

通常,为您创建的应用程序创建的第一个迁移将是 /0001_testing.py(这就是为什么需要更早命名它的原因)。由于此文件的内容在容器启动和 运行ning 时对容器可见,因此您将能够打印文件的内容。然后 运行 迁移命令。这会在 django_migrations table 中创建一个列,使 django 看起来已经应用了迁移。但是,在您的本地计算机上,此迁移文件不存在。所以从上面的打印语句中复制文件的内容,并将其放入一个与上面提到的同名的.py文件中,并保存在本地设备上上面的migrations文件夹中。

您可以通过重复该过程并根据需要递增 testing_migrations 文件中的数字,对所有后续迁移采用此方法。

完成 table 后压缩迁移会有所帮助。如果你在开发中做这一切并且不需要 roll-back 对数据库模式的更改,那么只需在删除所有迁移文件和 django_migrations [=34] 中的行后将其投入生产=] 与您最初完成的应用相对应。放下你的 table 并让你的第一个新迁移文件 re-create 它们然后再次导入你的数据。

这不是推荐的方法。如果您不在 c运行ch.

时间,请使用 deosha's