尝试删除第三方Django应用程序时出现迁移文件错误

6ioyuze2  于 2023-10-21  发布在  Go
关注(0)|答案(3)|浏览(152)

我正在做一个Django项目,目前使用的是第三方应用Oscar。我们正在从Oscar迁移到一个定制的商店,为此,我们希望摆脱一堆旧文件,模型,当然还有实际的第三方依赖关系。但我很难做到这一点,因为迁移文件不断抛出错误。
情况是,我们有第一方模型,依赖于奥斯卡的模型。举例来说:

from oscar.apps.catalogue.models import Product

class Executable(Model):
    exec_hash = CharField(max_length=64, unique=True)
    product = ForeignKey(Product, blank=True, null=True, on_delete=CASCADE)
    version = CharField(max_length=32)
    os = CharField(max_length=32)
    update_url = CharField(max_length=128, blank=True)

这意味着我们有一个迁移文件,其中包含创建此表的代码:

migrations.CreateModel(
        name="Executable",
        fields=[
            ("id", models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name="ID")),
            ("exec_hash", models.CharField(max_length=64, unique=True)),
            ("version", models.CharField(max_length=32)),
            ("os", models.CharField(max_length=32)),
            ("update_url", models.CharField(blank=True, max_length=128)),
            (
                "product",
                models.ForeignKey(
                    blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to="catalogue.product"
                ),
            ),
        ],
    ),

需要删除此Executable中的product字段,因此我从模型中删除了该字段并创建了一个新的迁移。
现在,我想从INSTALLED_APPS列表中删除所有Oscar应用程序,但这会引起很多麻烦,因为当我想创建或运行任何迁移时,我会收到以下错误:

ValueError: The field sr_app.Executable.product was declared with a lazy reference to 'catalogue.product', but app 'catalogue' isn't installed.

我试着从初始迁移文件中简单地删除这个字段,但是在下一次迁移中(这个字段实际上是从模型中删除的),我得到了一个关键错误:

Running migrations:
  Applying sr_app.0003_remove_executable_product...Traceback (most recent call last):
  [...snip...]
  File "/Users/kevin/Workspace/my_project_name/.venv/lib/python3.10/site-packages/django/db/migrations/operations/fields.py", line 162, in state_forwards
    old_field = model_state.fields.pop(self.name)
KeyError: 'product'

因此,似乎我必须永远安装Oscar和INSTALLED_APPS的一部分,因为初始迁移使用此信息?但是第一次迁移已经被应用了,所以第一次迁移需要在下一次迁移运行时有效,这有点烦人。
我怎样才能解决这个问题?当我自己的初始迁移依赖于Oscar(或任何第三方应用程序)时,我如何摆脱该第三方应用程序?

u4dcyp6a

u4dcyp6a1#

我在我的项目中也遇到过类似的情况。我尝试过压缩迁移,但遇到了循环依赖的问题,我还没有解决。
话虽如此,您可能希望尝试压缩迁移(请参阅https://docs.djangoproject.com/en/4.2/topics/migrations/#squashing-migrations),因为这将解决您的问题-一旦您的生产部署更新到这些压缩的迁移点,您就可以删除旧的迁移,然后一旦从项目及其迁移中删除了对应用程序的所有引用,您就可以从INSTALLED_APPS中删除应用程序。
简而言之,你运行./manage.py squashmigrations和你想要压缩的应用程序和迁移数量,Django将尝试通过删除在以后的迁移中添加然后删除的字段来优化迁移。

0h4hbjxa

0h4hbjxa2#

旧的迁移是出于兼容性的原因,如果您在不同的位置有多个版本的数据库状态,则需要它们(即,e.开发和生产服务器、开发人员个人电脑等)
如果您确定没有人使用尚未迁移的旧版本,则不需要旧的迁移。因此,只需确保在此项目中工作的每个人都迁移到最新版本的代码库,运行此代码的每个服务器也迁移,并从头开始重新创建迁移(删除所有迁移并创建新的)。
另一种解决方法是在旧的迁移中伪造此表:编辑第一次迁移,以这种方式引入与第三方表的关系,以便在数据库中创建相同的模型,并确保下一次迁移使用此假模型而不是第三方模型。然后编辑删除该关系的最新迁移,以便也删除伪模型。这也可能奏效。

6tdlim6h

6tdlim6h3#

我最近不得不从Django项目中的第三方应用程序迁移,并在迁移文件和依赖项方面遇到了类似的挑战。以下是我如何成功做到的:

第一步:创建新的字段删除迁移

您需要从我的Executable模型中删除一个字段(产品),该模型依赖于Oscar的“目录”应用程序。为此,您应该专门为此更改创建一个新迁移:

python manage.py makemigrations your_app_name

在这个新的迁移中,您应该从Executable模型中删除product字段。

第二步:更新迁移文件中的权限

在新的迁移文件(例如0003_remove_executable_product.py)中,您必须更新依赖项。有一行字是这样的:

dependencies = [
    ('sr_app', '0002_previous_migration'),
    ('catalogue', '0001_previous_migration'),  # Remove this line
]

您应该删除依赖于'catalogue'的行,因为您必须删除依赖于它的字段。

第三步:从已安装的LED_APPS中删除“catalogue”

现在安全地从Django项目设置中的Paddle_APPS列表中删除“catalogue”。

步骤4:应用迁移

最后,再次运行迁移以应用更改:

python manage.py migrate

第5步:清理奥斯卡专用代码

随着“catalogue”应用程序和产品字段依赖项的删除,您可以开始清理项目中任何其他奥斯卡特定的代码。
通过遵循这些步骤,您将很有可能能够安全地从项目中删除“目录”应用程序(Oscar),而不会遇到“惰性引用”错误。请记住备份您的数据并使用版本控制(例如Git)来跟踪此过程中的更改。此外,在删除第三方依赖项时要小心,因为它可能会影响项目的其他部分。

相关问题