如何更改 Django 应用程序的名称?
- 2025-02-25 09:08:00
- admin 原创
- 26
问题描述:
我通过重命名文件夹、导入和所有引用(模板/索引)更改了 Django 中应用程序的名称。但现在我尝试运行python manage.py runserver
Error: Could not import settings 'nameofmynewapp.settings' (Is it on sys.path?): No module named settings
我该如何调试并解决此错误?有什么线索吗?
解决方案 1:
按照以下步骤在 Django 中更改应用程序的名称:
重命名项目根目录中的文件夹
更改依赖项中对您应用程序的任何引用,即应用程序的
views.py
、、和文件urls.py
。manage.py
`settings.py`django_content_type
使用以下命令编辑数据库表:UPDATE 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+ 是否需要此步骤存在一些争议(在评论中);如果有人确切知道,请在此处更新。如果您
models.py
的元类已app_name
列出,请确保也重命名它(由@will 提及)。如果您已在应用内为
static
或templates
文件夹指定了命名空间,您还需要重命名它们。例如,重命名old_app/static/old_app
为new_app/static/new_app
。要重命名 django
models
,您需要更改django_content_type.name
DB 中的条目。对于 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 提到更新您要重命名的应用中的 apps.py 文件以使用新名称。将“<old_app_name>Config”类名更改为“<new_app_name>Config”,并在此类中将 name = '<old_app_name>' 更改为 name = '<new_app_name>'
元点(如果使用虚拟环境):值得注意的是,如果您重命名包含虚拟环境的目录,则您的环境中可能会有多个包含绝对路径的文件,也需要更新。如果您收到此类错误,ImportError: No module named ...
则可能是罪魁祸首。(感谢@danyamachine提供此信息)。
其他参考资料:您可能还想参考以下链接以获得更完整的图片:
使用 Django 和 South 重命名应用程序
如何将模型从一个 django 应用程序迁移到一个新的应用程序中?
如何更改 Django 应用程序的名称?
使用 Django South 进行向后迁移
使用 Django/South 重命名模型的最简单方法?
Python 代码(感谢A.Raouf)用于自动执行上述步骤(未经测试的代码。您已收到警告!)
Python 代码(感谢rafaponieman)用于自动执行上述步骤(未经测试的代码。您已收到警告!)
解决方案 2:
Django 1.7 中的新功能是应用程序注册表,用于存储配置并提供自省。此机制可让您更改多个应用程序属性。
我想强调的重点是,重命名应用程序并不总是必要的:通过应用程序配置可以解决冲突的应用程序。但如果您的应用程序需要友好的命名,这也是可行的方法。
举个例子,我想将我的投票应用命名为“用户反馈”。它如下所示:
apps.py
在目录中创建文件polls
:
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/
解决方案 3:
有趣的问题!我很快就要重命名很多应用程序,所以我进行了一次试运行。
此方法允许以原子步骤的方式取得进展,以最大限度地减少对正在重命名的应用程序上工作的其他开发人员的干扰。
请参阅此答案底部的链接以获取有效的示例代码。
为移动准备现有代码:
* 创建应用程序配置(设置`name`并`label`恢复默认值)。
* 将应用程序配置添加到`INSTALLED_APPS`。
* 在所有模型上,明确设置`db_table`为当前值。
* 医生迁移,因此`db_table`“总是”被明确定义。
* 确保不需要迁移(检查上一步)。
更改应用程序标签:
* 在应用程序配置中设置`label`为新的应用程序名称。
* 更新迁移和外键以引用新的应用标签。
* 更新通用的基于类的视图的模板(默认路径为`<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 上运行。
解决方案 4:
在很多情况下,我相信@allcaps 的答案很有效。
但是,有时确实需要重命名应用程序,例如为了提高代码的可读性或防止混淆。
大多数其他答案都涉及手动数据库操作或修改现有的迁移,我不太喜欢这样。
或者,我喜欢创建一个具有所需名称的新应用程序,复制所有内容,确保它正常运行,然后删除原始应用程序:
启动一个具有所需名称的新应用程序,并将原始应用程序中的所有代码复制到其中。确保在新复制的代码中修复命名空间内容,以匹配新应用程序名称。
makemigrations
和migrate
。注意:如果应用程序有很多外键,则在尝试运行复制应用程序的初始迁移时,反向访问器可能会发生冲突。您必须在旧应用程序上重命名 related_name 访问器(或添加新访问器)以解决冲突。创建数据迁移,将相关数据从原始应用程序的表复制到新应用程序的表中,然后
migrate
再次复制。
此时,一切仍然有效,因为原始应用程序及其数据仍然存在。
现在您可以重构所有依赖代码,这样它就只使用新应用程序了。请参阅其他答案,了解需要注意的事项的示例。
确定一切正常后,您可以删除原始应用程序。这涉及另一次(架构)迁移。
这样做的好处是,每一步都使用正常的 Django 迁移机制,无需手动操作数据库,而且我们可以在源代码控制中跟踪所有内容。此外,我们保留原始应用程序及其数据,直到我们确定一切正常为止。
解决方案 5:
如果您正在使用 PyCharm 并且项目在重命名后停止工作:
编辑运行/调试配置并更改环境变量 DJANGO_SETTINGS_MODULE,因为它包含您的项目名称。
转到设置/语言和框架/Django 并更新设置文件位置。
解决方案 6:
重新迁移方法以获得更清洁的盘子。
如果其他应用程序没有将要重命名的应用程序的外键模型作为外键,则可以轻松完成此操作。检查并确保它们的迁移文件未列出来自此应用程序的任何迁移。
备份数据库。转储所有表,其中 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.py
、、urls.py
“manage.py”和settings.py
文件。删除迁移:
delete from django_migrations where app = '<OldAppName>'
如果您
models.py
的元类已app_name
列出,请确保也重命名它(由@will 提及)。如果您已在应用内为
static
或templates
文件夹指定了命名空间,您还需要重命名它们。例如,重命名old_app/static/old_app
为new_app/static/new_app
。如果你在 apps.py 中定义了应用程序配置;请重命名这些配置,并在 settings.INSTALLED_APPS 中重命名它们的引用
删除迁移文件。
重新进行迁移并迁移。
从备份中加载表数据。
解决方案 7:
只需 4 个简单步骤即可重命名 Django 项目中的现有应用程序,不会造成任何麻烦或数据丢失。
步骤 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 迁移中更新旧的应用程序名称引用。
您可能需要做出的更改示例:
# 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 migration --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/文本编辑器的查找和替换功能来更改各个文件。
解决方案 8:
如果您使用Pycharm ,则通过重构(Shift
+F6
默认)所有项目文件,重命名应用程序非常容易。
但请确保删除__pycache__
项目目录及其子目录中的文件夹。还要小心,因为它还会重命名注释,您可以在它将向您显示的重构预览窗口中排除这些注释。此外,
您还必须在重命名的应用程序中重命名 OldNameConfig(AppConfig):。apps.py
如果您不想丢失数据库的数据,则必须像前面提到的答案一样手动使用数据库查询来执行此操作。
解决方案 9:
我的简单替代方法是避免手动数据库操作(类似于https://stackoverflow.com/a/64133141/1608851),在 CI/CD 中运行良好,并且是可逆的。
在“旧”应用中创建一个空迁移,重命名表、内容类型和迁移记录。包括反向迁移。示例:
from django.db import migrations
sql = """
ALTER TABLE oldapp_examplemodel RENAME TO newapp_examplemodel;
UPDATE django_migrations SET app ='newapp' WHERE app ='oldapp';
UPDATE django_content_type SET app_label ='newapp' WHERE app_label ='oldapp';
"""
reverse_sql = """
ALTER TABLE newapp_examplemodel RENAME TO oldapp_examplemodel;
UPDATE django_migrations SET app ='oldapp' WHERE app ='newapp';
UPDATE django_content_type SET app_label ='oldapp' WHERE app_label ='newapp';
"""
class Migration(migrations.Migration):
dependencies = [
('oldapp', '0001_initial'),
]
operations = [
migrations.RunSQL(sql, reverse_sql)
]
将模型表名称设置为 new_app。例如:
class ExampleModel(models.Model):
# normal column definitions...
class Meta:
db_table = "newapp_examplemodel" # add this line to the meta class
提交、测试并部署上述更改。
删除步骤1中创建的迁移。
重命名/移动旧应用程序并修复所有引用(有关更多详细信息,请参阅https://stackoverflow.com/a/8408131/1608851),包括迁移中的引用。
db_table
从模型元类中删除覆盖。提交、测试和部署。
笔记:
该
django_migrations
表将保留旧应用程序的一行,因为该行是在我们的新迁移运行之后、但在新应用程序名称下注册之前添加的。保留原样应该没问题。删除迁移是由于上述原因,但也是为了防止将来反向迁移时出现问题,也是因为
撤消此应用程序重命名需要从步骤 3 中检出/部署提交,然后撤消我们的迁移,然后检出/部署之前的提交
解决方案 10:
您现在可以使用django-rename-app工具。
安装django-rename-app包
将其添加到
INSTALLED_APPS
设置中将您的应用程序文件夹重命名为新名称
执行查找和替换以重命名存储库中所有出现的旧名称(例如在 vscode 中)
提交更改
运行该工具:
python manage.py rename_app old_app new_app
欲了解更详细说明,请访问:
解决方案 11:
相反,我们可以这样做吗?
使用 NewName 创建新的应用程序,移动所有模型、视图,在导入时适当更改应用程序内的名称,放弃旧应用程序。
只是一个想法。
解决方案 12:
为什么不直接使用“查找和替换”选项(每个代码编辑器都有它)?
例如 Visual Studio Code(在编辑选项下):
您只需输入旧名称和新名称,然后单击即可替换项目中的所有内容。
注意:这只会重命名文件内容,而不会重命名文件和文件夹名称。不要忘记重命名文件夹,例如templates/my_app_name/
将其重命名为templates/my_app_new_name/