我在Django中修改了一个应用的名字,重命名了它的文件夹、导入和所有引用(模板/索引)。但是现在,当我试图运行python manage.py runserver时,我得到了这个错误

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

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


当前回答

重新迁移,寻找更干净的板块。

这可以毫不痛苦地做,如果其他应用程序没有外键模型从应用程序被重命名。检查并确保他们的迁移文件没有列出任何来自此迁移的迁移。

Backup your database. Dump all tables with a) data + schema for possible circular dependencies, and b) just data for reloading. Run your tests. Check all code into VCS. Delete the database tables of the app to be renamed. Delete the permissions: delete from auth_permission where content_type_id in (select id from django_content_type where app_label = '<OldAppName>') Delete content types: delete from django_content_type where app_label = '<OldAppName>' Rename the folder of the app. Change any references to your app in their dependencies, i.e. the app's views.py, urls.py , 'manage.py' , and settings.py files. Delete migrations: delete from django_migrations where app = '<OldAppName>' If your models.py 's Meta Class has app_name listed, make sure to rename that too (mentioned by @will). If you've namespaced your static or templates folders inside your app, you'll also need to rename those. For example, rename old_app/static/old_app to new_app/static/new_app. If you defined app config in apps.py; rename those, and rename their references in settings.INSTALLED_APPS Delete migration files. Re-make migrations, and migrate. Load your table data from backups.

其他回答

简单的4步重命名Django项目中现有的应用程序,没有任何痛苦或数据丢失。

步骤1

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

Mv ./old_app ./new_app . Mv ./old_app . Mv

步骤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 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 /文本编辑器的查找和替换功能来更改各种文件。

有趣的问题!我很快就要给很多应用重命名了,所以我先做了个预演。

这种方法允许在原子步骤中取得进展,以最大限度地减少对正在重命名应用程序的其他开发人员的干扰。

请参阅答案底部的链接,以获得工作示例代码。

Prepare existing code for the move: Create an app config (set name and label to defaults). Add the app config to INSTALLED_APPS. On all models, explicitly set db_table to the current value. Doctor migrations so that db_table was "always" explicitly defined. Ensure no migrations are required (checks previous step). Change the app label: Set label in app config to new app name. Update migrations and foreign keys to reference new app label. Update templates for generic class-based views (the default path is <app_label>/<model_name>_<suffix>.html) Run raw SQL to fix migrations and content_types app (unfortunately, some raw SQL is unavoidable). You can not run this in a migration. UPDATE django_migrations SET app = 'catalogue' WHERE app = 'shop'; UPDATE django_content_type SET app_label = 'catalogue' WHERE app_label = 'shop'; Ensure no migrations are required (checks previous step). Rename the tables: Remove "custom" db_table. Run makemigrations so django can rename the table "to the default". Move the files: Rename module directory. Fix imports. Update app config's name. Update where INSTALLED_APPS references the app config. Tidy up: Remove custom app config if it's no longer required. If app config gone, don't forget to also remove it from INSTALLED_APPS.


示例解决方案:我已经创建了app-rename- Example,一个示例项目,在这里你可以看到我如何重命名一个应用程序,一次提交一次。

这个例子使用的是Python 2.7和Django 1.8,但我相信同样的过程至少可以在Python 3.6和Django 2.1上工作。

重新迁移,寻找更干净的板块。

这可以毫不痛苦地做,如果其他应用程序没有外键模型从应用程序被重命名。检查并确保他们的迁移文件没有列出任何来自此迁移的迁移。

Backup your database. Dump all tables with a) data + schema for possible circular dependencies, and b) just data for reloading. Run your tests. Check all code into VCS. Delete the database tables of the app to be renamed. Delete the permissions: delete from auth_permission where content_type_id in (select id from django_content_type where app_label = '<OldAppName>') Delete content types: delete from django_content_type where app_label = '<OldAppName>' Rename the folder of the app. Change any references to your app in their dependencies, i.e. the app's views.py, urls.py , 'manage.py' , and settings.py files. Delete migrations: delete from django_migrations where app = '<OldAppName>' If your models.py 's Meta Class has app_name listed, make sure to rename that too (mentioned by @will). If you've namespaced your static or templates folders inside your app, you'll also need to rename those. For example, rename old_app/static/old_app to new_app/static/new_app. If you defined app config in apps.py; rename those, and rename their references in settings.INSTALLED_APPS Delete migration files. Re-make migrations, and migrate. Load your table data from backups.

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

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

您只需输入旧名称和新名称,并替换项目中的所有内容,只需单击一下。

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

在很多情况下,我认为@allcaps的答案效果很好。

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

大多数其他答案都涉及手工数据库操作或对现有迁移进行修补,我不太喜欢这种方法。

作为一种替代方法,我喜欢用想要的名称创建一个新的应用程序,复制所有内容,确保它可以工作,然后删除原来的应用程序:

Start a new app with the desired name, and copy all code from the original app into that. Make sure you fix the namespaced stuff, in the newly copied code, to match the new app name. makemigrations and migrate. Note: if the app has a lot of foreign keys, there will likely be issues with clashing reverse accessors when trying to run the initial migration for the copied app. You have to rename the related_name accessor (or add new ones) on the old app to resolve the clashes. Create a data migration that copies the relevant data from the original app's tables into the new app's tables, and migrate again.

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

现在你可以重构所有的依赖代码,所以它只使用新的应用程序。有关需要注意的例子,请参阅其他答案。 一旦你确定一切正常,你可以删除原来的应用程序。这涉及到另一种(模式)迁移。

这样做的好处是,每一步都使用正常的Django迁移机制,不需要手动操作数据库,我们可以跟踪源代码控制中的所有内容。此外,我们将保留原始应用程序及其数据,直到我们确定一切正常为止。