如何更改 Django 应用程序的名称?

Posted

技术标签:

【中文标题】如何更改 Django 应用程序的名称?【英文标题】:How to change the name of a Django app? 【发布时间】:2012-01-14 12:50:42 【问题描述】:

我通过重命名应用程序的文件夹、导入和所有引用(模板/索引)来更改 Django 中应用程序的名称。但现在当我尝试运行python manage.py runserver时出现此错误@

Error: Could not import settings 'nameofmynewapp.settings' (Is it on sys.path?): No module named settings

如何调试和解决此错误?有什么线索吗?

【问题讨论】:

嗨 danihp。是的,我有。我也在用virtualenv,不知道跟这个有没有关系。 如果您有机会使用 PyCharm,它的rename 功能将极大地帮助您。 南方不支持这样的操作吗? @andi ***.com/questions/4566978/… pip install django-rename-app 然后 python manage.py rename_app <old_app_name> <new_app_name> , github.com/odwyersoftware/django-rename-app 【参考方案1】:

按照以下步骤在 Django 中更改应用的名称:

    重命名项目根目录中的文件夹 在依赖项中更改对您应用的所有引用,即应用的 views.pyurls.pymanage.pysettings.py 文件。 使用以下命令编辑数据库表django_content_typeUPDATE django_content_type SET app_label='<NewAppName>' WHERE app_label='<OldAppName>' 此外,如果您有模型,则必须重命名模型表。对于 postgres,请使用 ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName。对于 mysql 也是如此,我认为它是相同的(正如 @null_radix 所提到的)。 (对于 Django >= 1.7)更新 django_migrations 表以避免重新运行之前的迁移:UPDATE django_migrations SET app='<NewAppName>' WHERE app='<OldAppName>'注意:如果 Django 1.8+ 需要此步骤,则存在一些争议(在 cmets 中);如果有人确定,请在此处更新。 如果您的models.py 的元类列出了app_name,请确保也重命名它(@will 提到)。 如果您在应用程序中为 statictemplates 文件夹命名,您还需要重命名这些文件夹。例如,将old_app/static/old_app 重命名为new_app/static/new_app。 要重命名 django models,您需要更改 DB 中的 django_content_type.name 条目。对于 postgreSQL,请使用 UPDATE django_content_type SET name='<newModelName>' where name='<oldModelName>' AND app_label='<OldAppName>' 2021 年 7 月 16 日更新:另外,必须删除应用程序内的 __pycache__/ 文件夹,否则您会得到 EOFError: marshal data too short when trying to run the server。由@Serhii Kushchenko 提及

元点(如果使用 virtualenv): 值得注意的是,如果您要重命名包含您的 virtualenv 的目录,那么您的 env 中可能会有几个包含绝对路径的文件,并且还需要要被更新。如果您收到诸如ImportError: No module named ... 之类的错误,这可能是罪魁祸首。 (感谢@danyamachine 提供这个)。

其他参考资料:您可能还想参考以下链接以获得更完整的图片:

    Renaming an app with Django and South How do I migrate a model out of one django app and into a new one? How to change the name of a Django app? Backwards migration with Django South Easiest way to rename a model using Django/South? Python code(感谢A.Raouf)自动执行上述步骤(未经测试的代码。您已被警告!) Python code(感谢rafaponieman)自动执行上述步骤(未经测试的代码。您已被警告!)

【讨论】:

此外,如果您有模型,则必须重命名模型表。对于 postgres 使用 ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName 如果您使用新的迁移,您需要更改现有迁移文件和 django_migrations 表中的应用名称。最好先压缩迁移,这样可以减少编辑。 对于 Postgres,如果您也想重命名序列,请使用 ALTER SEQUENCE <oldAppName>_<modelName>_<PK>_seq RENAME TO <newAppName>_<modelName>_<PK>_seq;。虽然没有必要,但系统本身并不关心名称。 DEFAULT 列存储OID ('foo_pkey_seq'::regclass),您可以更改序列的名称而不会破坏它 - OID 保持不变。 如果您更新您的答案以包含 James 关于升级迁移 files (例如依赖模块名称)所说的话,那就太好了......无法完全弄清楚有点。 这是一个管理命令,允许根据@SrikarAppalaraju 的解决方案重命名模型:gist.github.com/rafaponieman/201054ddf725cda1e60be3fe845850a5 它接受 old_name、new_name 和 classes 作为参数(所有格式都与它们在数据库表和字段上的外观相同)。 【参考方案2】:

在很多情况下,我相信@allcaps 的answer 效果很好。

但是,有时需要实际重命名应用程序,例如以提高代码可读性或防止混淆。

大多数其他答案涉及manual database manipulation 或tinkering with existing migrations,我不太喜欢。

作为替代方案,我喜欢创建一个具有所需名称的新应用,复制所有内容,确保其正常工作,然后删除原始应用:

    使用所需名称启动一个应用程序,并将原始应用程序中的所有代码复制到该应用程序中。确保在新复制的代码中修复命名空间的内容,以匹配新的应用名称。

    makemigrationsmigrate。注意:如果应用程序有很多外键,则在尝试为复制的应用程序运行初始迁移时,可能会出现反向访问器冲突的问题。您必须在旧应用上重命名related_name 访问器(或添加新访问器)才能解决冲突。

    创建一个data migration,将原始应用表中的相关数据复制到新应用的表中,然后再次migrate

此时,一切仍然正常,因为原始应用及其数据仍然存在。

    现在您可以重构所有依赖代码,因此它只使用新应用程序。有关注意事项的示例,请参阅其他答案。

    确定一切正常后,您可以删除原始应用。这涉及另一个(模式)迁移。

这样做的好处是每一步都使用正常的 Django 迁移机制,无需手动操作数据库,而且我们可以在源代码管理中跟踪所有内容。此外,在确定一切正常之前,我们会保留原始应用及其数据。

【讨论】:

虽然如果您想在删除原始应用程序后在全新安装上运行迁移,猜测这会导致问题,对吧?因为数据迁移将指向一个现在不存在的应用程序。 @OzgurAkcali:我认为全新安装应该不是问题,因为数据迁移指定依赖关系,就像任何其他迁移一样,并且它们(应该)使用历史模型。数据迁移不会做任何事情,因为没有要迁移的数据。但是,如果是全新的安装,我会从头开始,所以要么删除所有迁移并创建新迁移,要么全部压缩。 嗯,是的,他们应该使用历史模型。想知道这样的一行是否会引起问题:apps.get_model('old_app', 'ModelName') 当旧应用程序被删除时。如果那是安全的,那么我想在第 5 步之后运行第 3 步也是安全的。 @OzgurAkcali:我不认为apps.get_model() 会在删除旧应用时造成问题。相反,这就是它的用途:apps.get_model() 返回一个“伪”模型,它是根据迁移历史构建的。在迁移历史的那个时刻,该应用程序仍然存在。请参阅文档 here 和 here。 这似乎比这里提到的其他方法更简洁。【参考方案3】:

在 Django 项目中重命名现有应用的简单 4 个步骤,不会造成任何痛苦或数据丢失。

第 1 步

重命名应用文件夹。在本例中,“old_app”是我们的旧名称,“new_app”是我们的新名称”。

mv ./old_app ./new_app

第 2 步

更新所有引用旧文件夹的导入以引用新文件夹。

例如:

# Before 
from myproject.old_app import models

# After
from myproject.new_app import models

第 3 步

更新Django migrations 中的旧应用名称引用。

您可能需要进行的更改示例:

# Before

dependencies = [
    ('old_app', '0023_auto_20200403_1050'),
]

# After

dependencies = [
    ('new_app', '0023_auto_20200403_1050'),
]

# Before

field = models.ForeignKey(
    default=None, on_delete=django.db.models.deletion.CASCADE,
    to='old_app.Experiment'
)

# After

field = models.ForeignKey(
    default=None, on_delete=django.db.models.deletion.CASCADE,
    to='new_app.Experiment'
)

第 4 步

此时进行提交。

然后,无论您在已部署环境中运行应用程序迁移,在该过程中运行迁移之前运行django_rename_app。

即在“python manage.py migrate --noinput”之前,如下例所示。

# Before

python manage.py collectstatic --noinput
python manage.py migrate --noinput
gunicorn my_project.wsgi:application

# After

python manage.py collectstatic --noinput
python manage.py rename_app old_app new_app
python manage.py migrate --noinput
gunicorn my_project.wsgi:application

这将更新以下内部 Django 数据库表中的应用名称:

django_content_type django_migrations

重命名所有表格的前缀,以新的应用名称开头,而不是旧的。

就是这样。

注意:最好使用 IDE/文本编辑器的查找和替换功能来更改各种文件。

【讨论】:

【参考方案4】:

如果您使用 Pycharm,通过 重构Shift+F6 默认)对所有项目文件重命名应用程序非常容易。 但请确保删除项目目录及其子目录中的 __pycache__ 文件夹。还要小心,因为它也会重命名 cmets,您可以在它将显示给您的重构预览窗口中将其排除。 此外,您还必须在重命名的应用程序的 apps.py 中重命名 OldNameConfig(AppConfig):。

如果您不想丢失数据库的数据,则必须像上述答案一样在数据库中进行查询。

【讨论】:

【参考方案5】:

为什么不直接使用“查找和替换”选项。 (每个代码编辑器都有)?

例如 Visual Studio Code(在编辑选项下):

您只需输入旧名称和新名称,然后一键替换项目中的所有内容。

注意:这只会重命名文件内容,而不是文件和文件夹名称。不要忘记重命名文件夹,例如。 templates/my_app_name/ 重命名为 templates/my_app_new_name/

【讨论】:

【参考方案6】:

有趣的问题!我很快将不得不重命名很多应用程序,所以我进行了试运行。

此方法允许在原子步骤中取得进展,以尽量减少对正在重命名的应用程序上工作的其他开发人员的干扰。

有关工作示例代码,请参阅此答案底部的链接。

    为移动准备现有代码: 创建一个app config(将namelabel 设置为默认值)。 将应用配置添加到INSTALLED_APPS。 在所有模型上,将 db_table 显式设置为当前值。 医生迁移,以便“始终”明确定义 db_table。 确保不需要迁移(检查上一步)。

    更改应用标签

    将应用配置中的label 设置为新的应用名称。 更新迁移和外键以引用新的应用标签。 为基于类的通用视图更新模板 (default path is <app_label>/<model_name>_<suffix>.html)

    运行原始 SQL 来修复迁移和content_types 应用程序(不幸的是,一些原始 SQL 是不可避免的)。 您不能在迁移中运行它。

    UPDATE django_migrations
       SET app = 'catalogue'
     WHERE app = 'shop';
    
    UPDATE django_content_type
       SET app_label = 'catalogue'
     WHERE app_label = 'shop';
    

    确保不需要迁移(检查上一步)。

    重命名表格: 删除“自定义”db_table。 运行makemigrations,以便 django 可以将表重命名为“默认”。 移动文件: 重命名模块目录。 修复导入。 更新应用配置的name。 更新INSTALLED_APPS 引用应用配置的位置。 整理: 如果不再需要自定义应用配置,请删除它。 如果应用配置消失,别忘了将其从INSTALLED_APPS 中删除。

示例解决方案:我创建了app-rename-example,这是一个示例项目,您可以在其中看到我如何重命名应用程序,一次提交一个。

该示例使用 Python 2.7 和 Django 1.8,但我相信相同的过程至少适用于 Python 3.6 和 Django 2.1。

【讨论】:

谢谢@meshy。它确实帮助我重命名了一个巨大的应用程序。一个建议是,在运行最后一次迁移后,您可以删除所有迁移文件并重新创建初始迁移文件,如果您正在进行任何持续集成测试,这将对您有所帮助,否则 CI 将无法创建测试数据库。 我写这篇文章的目的是希望迁移完成后可以从头开始运行。如果迁移失败,也许我们中的一个人错过了一些东西。我会考虑一下,看看是否还有其他需要添加的步骤。 @Rohan 您是否可以提供任何信息来详细说明迁移是如何失败的? 如果您使用旧迁移文件在本地运行测试,您会看到创建表将失败@meshy 这个游戏计划非常适合我。只要在处理下一步之前通过所有活动的检查(CI、其他开发人员、生产等)部署每个步骤,它就可以完美地工作——现有的历史迁移没有问题。按顺序执行这些步骤,并将更改传播到各处,然后再进行下一步。【参考方案7】:

重新迁移方法以获得更清洁的印版。

如果其他应用程序没有要重命名的应用程序的外键模型,则可以轻松完成此操作。检查并确保他们的迁移文件没有列出来自该文件的任何迁移。

    备份您的数据库。转储所有表,包括 a) 可能的循环依赖的数据 + 模式,以及 b) 仅用于重新加载的数据。 运行您的测试。 将所有代码签入 VCS。 删除要重命名的应用的数据库表。 删除权限:delete from auth_permission where content_type_id in (select id from django_content_type where app_label = '<OldAppName>') 删除内容类型:delete from django_content_type where app_label = '<OldAppName>' 重命名应用程序的文件夹。 在依赖项中更改对您应用的所有引用,即应用的 views.pyurls.py、'manage.py' 和 settings.py 文件。 删除迁移:delete from django_migrations where app = '<OldAppName>' 如果您的models.py 的元类列出了app_name,请确保也重命名(@will 提到)。 如果您在应用程序中为 statictemplates 文件夹命名,您还需要重命名这些文件夹。例如,将old_app/static/old_app 重命名为new_app/static/new_app。 如果您在 apps.py 中定义了应用配置;重命名它们,并在 settings.INSTALLED_APPS 中重命名它们的引用 删除迁移文件。 重新进行迁移,然后迁移。 从备份中加载表数据。

【讨论】:

【参考方案8】:

如果您使用 PyCharm 并且项目在重命名后停止工作:

    编辑运行/调试配置并更改环境变量 DJANGO_SETTINGS_MODULE,因为它包含您的项目名称。 转到设置/语言和框架/Django 并更新设置文件位置。

【讨论】:

这是查找和替换失败的情况之一。感谢您指出这一点。【参考方案9】:

Django 1.7 中的新功能是一个应用注册表,用于存储配置并提供自省功能。这个机制可以让你改变几个应用属性。

我想说的主要一点是,重命名应用程序并不总是必要的:通过应用程序配置,可以解决冲突的应用程序。如果您的应用需要友好的命名,这也是一种可行的方法。

例如,我想将我的投票应用命名为“来自用户的反馈”。它是这样的:

polls目录下创建apps.py文件:

from django.apps import AppConfig

class PollsConfig(AppConfig):
    name = 'polls'
    verbose_name = "Feedback from users"

将默认应用配置添加到您的polls/__init__.py

default_app_config = 'polls.apps.PollsConfig'

更多应用配置:https://docs.djangoproject.com/en/1.7/ref/applications/

【讨论】:

以上是关于如何更改 Django 应用程序的名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django、python 中更改管理字段名称

使用 manage.py shell 更改 Django 站点显示名称?

如何在 Django REST 框架中更改字段名称

更改应用程序名称和数据库表后 Django 无法进行迁移

如何更改在 MAMP 上运行的 Django 项目数据库名称?

覆盖 Django 表单字段的名称 attr