如何更改 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.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+ 需要此步骤,则存在一些争议(在 cmets 中);如果有人确定,请在此处更新。
如果您的models.py
的元类列出了app_name
,请确保也重命名它(@will 提到)。
如果您在应用程序中为 static
或 templates
文件夹命名,您还需要重命名这些文件夹。例如,将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,我不太喜欢。
作为替代方案,我喜欢创建一个具有所需名称的新应用,复制所有内容,确保其正常工作,然后删除原始应用:
使用所需名称启动一个新应用程序,并将原始应用程序中的所有代码复制到该应用程序中。确保在新复制的代码中修复命名空间的内容,以匹配新的应用名称。
makemigrations
和 migrate
。注意:如果应用程序有很多外键,则在尝试为复制的应用程序运行初始迁移时,可能会出现反向访问器冲突的问题。您必须在旧应用上重命名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(将
name
和label
设置为默认值)。
将应用配置添加到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.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 中重命名它们的引用
删除迁移文件。
重新进行迁移,然后迁移。
从备份中加载表数据。
【讨论】:
【参考方案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 应用程序的名称?的主要内容,如果未能解决你的问题,请参考以下文章
使用 manage.py shell 更改 Django 站点显示名称?