简体   繁体   English

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

[英]How to change the name of a Django app?

I have changed the name of an app in Django by renaming its folder, imports and all its references (templates/indexes).我通过重命名其文件夹、导入及其所有引用(模板/索引)来更改 Django 中应用程序的名称。 But now I get this error when I try to run python manage.py runserver但是现在当我尝试运行python manage.py runserver时出现此错误

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

How can I debug and solve this error?我该如何调试和解决这个错误? Any clues?有什么线索吗?

Follow these steps to change an app's name in Django:按照以下步骤在 Django 中更改应用程序的名称:

  1. Rename the folder which is in your project root重命名项目根目录中的文件夹
  2. Change any references to your app in their dependencies, ie the app's views.py , urls.py , 'manage.py' , and settings.py files.在它们的依赖项中更改对您的应用程序的任何引用,即应用程序的views.pyurls.py 、 'manage.py' 和settings.py文件。
  3. Edit the database table django_content_type with the following command: UPDATE django_content_type SET app_label='<NewAppName>' WHERE app_label='<OldAppName>'使用以下命令编辑数据库表django_content_typeUPDATE django_content_type SET app_label='<NewAppName>' WHERE app_label='<OldAppName>'
  4. Also if you have models, you will have to rename the model tables.此外,如果您有模型,则必须重命名模型表。 For postgres use ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName .对于 postgres 使用ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName For mysql too I think it is the same (as mentioned by @null_radix)对于 mysql,我也认为它是相同的(如@null_radix 所述)
  5. (For Django >= 1.7) Update the django_migrations table to avoid having your previous migrations re-run: UPDATE django_migrations SET app='<NewAppName>' WHERE app='<OldAppName>' . (对于 Django >= 1.7)更新django_migrations表以避免重新运行之前的迁移: UPDATE django_migrations SET app='<NewAppName>' WHERE app='<OldAppName>' Note : there is some debate (in comments) if this step is required for Django 1.8+;注意:如果 Django 1.8+ 需要此步骤,则存在一些争论(在评论中); If someone knows for sure please update here.如果有人确定,请在此处更新。
  6. If your models.py 's Meta Class has app_name listed, make sure to rename that too (mentioned by @will).如果您的models.py的 Meta Class 列出了app_name ,请确保也将其重命名(@will 提到)。
  7. If you've namespaced your static or templates folders inside your app, you'll also need to rename those.如果您已在应用程序中为statictemplates文件夹命名,则还需要重命名它们。 For example, rename old_app/static/old_app to new_app/static/new_app .例如,将old_app/static/old_app重命名为new_app/static/new_app
  8. For renaming django models , you'll need to change django_content_type.name entry in DB.要重命名 django models ,您需要更改数据库中的django_content_type.name条目。 For postgreSQL use UPDATE django_content_type SET name='<newModelName>' where name='<oldModelName>' AND app_label='<OldAppName>'对于 postgreSQL 使用UPDATE django_content_type SET name='<newModelName>' where name='<oldModelName>' AND app_label='<OldAppName>'
  9. Update 16Jul2021 : Also, the __pycache__/ folder inside the app must be removed, otherwise you get EOFError: marshal data too short when trying to run the server . 2021 年 7 月 16更新:此外,必须删除应用程序内的__pycache__/文件夹,否则EOFError: marshal data too short when trying to run the server会出现EOFError: marshal data too short when trying to run the server Mentioned by @Serhii Kushchenko由@Serhii Kushchenko 提及

Meta point (If using virtualenv): Worth noting, if you are renaming the directory that contains your virtualenv, there will likely be several files in your env that contain an absolute path and will also need to be updated.元点(如果使用 virtualenv):值得注意的是,如果您正在重命名包含您的 virtualenv 的目录,您的 env 中可能会有几个包含绝对路径的文件,并且也需要更新。 If you are getting errors such as ImportError: No module named ... this might be the culprit.如果您收到诸如ImportError: No module named ...类的ImportError: No module named ...这可能是罪魁祸首。 (thanks to @danyamachine for providing this). (感谢@danyamachine 提供此信息)。

Other references: you might also want to refer the below links for a more complete picture其他参考:您可能还想参考以下链接以获得更完整的图片

  1. Renaming an app with Django and South 使用 Django 和 South 重命名应用程序
  2. How do I migrate a model out of one django app and into a new one? 如何将模型从一个 django 应用程序迁移到新的应用程序中?
  3. How to change the name of a Django app? 如何更改 Django 应用程序的名称?
  4. Backwards migration with Django South 使用 Django South 向后迁移
  5. Easiest way to rename a model using Django/South? 使用 Django/South 重命名模型的最简单方法?
  6. Python code (thanks to A.Raouf ) to automate the above steps (Untested code. You have been warned!) Python 代码(感谢A.Raouf )自动执行上述步骤(未经测试的代码。您已被警告!)
  7. Python code (thanks to rafaponieman ) to automate the above steps (Untested code. You have been warned!) Python 代码(感谢rafaponieman )自动执行上述步骤(未经测试的代码。您已被警告!)

New in Django 1.7 is a app registry that stores configuration and provides introspection. Django 1.7 中的新功能是一个应用程序注册表,用于存储配置并提供自省。 This machinery let's you change several app attributes.这个机器让你改变几个应用程序属性。

The main point I want to make is that renaming an app isn't always necessary: With app configuration it is possible to resolve conflicting apps.我想说的主要观点是重命名应用程序并不总是必要的:通过应用程序配置可以解决冲突的应用程序。 But also the way to go if your app needs friendly naming.但如果您的应用程序需要友好命名,这也是可行的方法。

As an example I want to name my polls app 'Feedback from users'.例如,我想将我的投票应用程序命名为“来自用户的反馈”。 It goes like this:它是这样的:

Create a apps.py file in the polls directory:polls目录中创建一个apps.py文件:

from django.apps import AppConfig

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

Add the default app config to your polls/__init__.py :将默认应用配置添加到您的polls/__init__.py

default_app_config = 'polls.apps.PollsConfig'

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

Fun problem!有趣的问题! I'm going to have to rename a lot of apps soon, so I did a dry run.很快我将不得不重命名很多应用程序,所以我做了一次试运行。

This method allows progress to be made in atomic steps, to minimise disruption for other developers working on the app you're renaming.此方法允许在原子步骤中取得进展,以尽量减少对正在重命名的应用程序上工作的其他开发人员的干扰。

See the link at the bottom of this answer for working example code.有关工作示例代码,请参阅此答案底部的链接。

  1. Prepare existing code for the move :为移动准备现有代码
    • Create an app config (set name and label to defaults).创建应用配置(将namelabel设置为默认值)。
    • Add the app config to INSTALLED_APPS .将应用程序配置添加到INSTALLED_APPS
    • On all models, explicitly set db_table to the current value.在所有模型上,将db_table显式设置为当前值。
    • Doctor migrations so that db_table was "always" explicitly defined.医生迁移以便db_table被“始终”明确定义。
    • Ensure no migrations are required (checks previous step).确保不需要迁移(检查上一步)。
  2. Change the app label :更改应用标签

    • Set label in app config to new app name.将应用配置中的label设置为新的应用名称。
    • 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 )更新基于类的通用视图的模板( 默认路径是<app_label>/<model_name>_<suffix>.html
    • Run raw SQL to fix migrations and content_types app (unfortunately, some raw SQL is unavoidable).运行原始 SQL 来修复迁移和content_types应用程序(不幸的是,一些原始 SQL 是不可避免的)。 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).确保不需要迁移(检查上一步)。

  3. Rename the tables :重命名表
    • Remove "custom" db_table .删除“自定义” db_table
    • Run makemigrations so django can rename the table "to the default".运行makemigrations以便 django 可以将表重命名为“默认值”。
  4. Move the files :移动文件
    • Rename module directory.重命名模块目录。
    • Fix imports.修复进口。
    • Update app config's name .更新应用配置的name
    • Update where INSTALLED_APPS references the app config.更新INSTALLED_APPS引用应用程序配置的位置。
  5. 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 .如果应用程序配置不见了,不要忘记也将其从INSTALLED_APPS删除。

Example solution: I've created app-rename-example , an example project where you can see how I renamed an app, one commit at a time.示例解决方案:我创建了app-rename-example ,这是一个示例项目,您可以在其中查看我如何重命名应用程序,一次提交一次。

The example uses Python 2.7 and Django 1.8, but I'm confident the same process will work on at least Python 3.6 and Django 2.1.该示例使用 Python 2.7 和 Django 1.8,但我相信相同的过程至少适用于 Python 3.6 和 Django 2.1。

In case you are using PyCharm and project stops working after rename:如果您正在使用 PyCharm 并且项目在重命名后停止工作:

  1. Edit Run/Debug configuration and change environment variable DJANGO_SETTINGS_MODULE, since it includes your project name.编辑运行/调试配置并更改环境变量 DJANGO_SETTINGS_MODULE,因为它包含您的项目名称。
  2. Go to Settings / Languages & Frameworks / Django and update the settings file location.转到 Settings / Languages & Frameworks / Django 并更新设置文件位置。

In many cases, I believe @allcaps's answer works well.在许多情况下,我相信@allcaps 的回答很有效。

However, sometimes it is necessary to actually rename an app, eg to improve code readability or prevent confusion.但是,有时需要实际重命名应用程序,例如提高代码可读性或防止混淆。

Most of the other answers involve either manual database manipulation or tinkering with existing migrations , which I do not like very much.大多数其他答案涉及手动数据库操作修补现有的迁移,我不太喜欢这些。

As an alternative, I like to create a new app with the desired name, copy everything over, make sure it works, then remove the original app:作为替代方案,我喜欢创建一个具有所需名称的新应用程序,复制所有内容,确保其正常工作,然后删除原始应用程序:

  1. 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.确保在新复制的代码中修复命名空间的内容,以匹配新的应用程序名称。

  2. makemigrations and migrate . makemigrationsmigrate 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.您必须重命名旧应用程序上的 related_name 访问器(或添加新访问器)以解决冲突。

  3. Create a data migration that copies the relevant data from the original app's tables into the new app's tables, and migrate again.创建数据迁移,将相关数据从原始应用的表复制到新应用的表中,然后再次migrate

At this point, everything still works, because the original app and its data are still in place.此时,一切仍然有效,因为原始应用程序及其数据仍然存在。

  1. Now you can refactor all the dependent code, so it only makes use of the new app.现在你可以重构所有的依赖代码,所以它只使用新的应用程序。 See other answers for examples of what to look out for.有关需要注意的事项的示例,请参阅其他答案。

  2. Once you are certain that everything works, you can remove the original app.一旦确定一切正常,您就可以删除原始应用程序。 This involves another (schema) migration.这涉及另一个(架构)迁移。

This has the advantage that every step uses the normal Django migration mechanism, without manual database manipulation, and we can track everything in source control.这样做的好处是每一步都使用正常的Django迁移机制,无需手动操作数据库,我们可以在源代码控制中跟踪所有内容。 In addition, we keep the original app and its data in place until we are sure everything works.此外,我们会保留原始应用程序及其数据,直到我们确定一切正常。

Re-migrate approach for a cleaner plate.重新迁移方法以获得更清洁的印版。

This can painlessly be done IF other apps do not foreign key models from the app to be renamed.如果其他应用程序没有来自要重命名的应用程序的外键模型,则可以轻松完成此操作。 Check and make sure their migration files don't list any migrations from this one.检查并确保他们的迁移文件没有列出来自这个的任何迁移。

  1. Backup your database.备份您的数据库。 Dump all tables with a) data + schema for possible circular dependencies, and b) just data for reloading.使用 a) 数据 + 模式转储所有表以获取可能的循环依赖,以及 b) 仅用于重新加载的数据。
  2. Run your tests.运行您的测试。
  3. Check all code into VCS.将所有代码签入 VCS。
  4. Delete the database tables of the app to be renamed.删除要重命名的应用的数据库表。
  5. Delete the permissions: delete from auth_permission where content_type_id in (select id from django_content_type where app_label = '<OldAppName>')删除权限: delete from auth_permission where content_type_id in (select id from django_content_type where app_label = '<OldAppName>')
  6. Delete content types: delete from django_content_type where app_label = '<OldAppName>'删除内容类型: delete from django_content_type where app_label = '<OldAppName>'
  7. Rename the folder of the app.重命名应用程序的文件夹。
  8. Change any references to your app in their dependencies, ie the app's views.py , urls.py , 'manage.py' , and settings.py files.在它们的依赖项中更改对您的应用程序的任何引用,即应用程序的views.pyurls.py 、 'manage.py' 和settings.py文件。
  9. Delete migrations: delete from django_migrations where app = '<OldAppName>'删除迁移: delete from django_migrations where app = '<OldAppName>'
  10. If your models.py 's Meta Class has app_name listed, make sure to rename that too (mentioned by @will).如果您的models.py的 Meta Class 列出了app_name ,请确保也将其重命名(@will 提到)。
  11. If you've namespaced your static or templates folders inside your app, you'll also need to rename those.如果您已在应用程序中为statictemplates文件夹命名,则还需要重命名它们。 For example, rename old_app/static/old_app to new_app/static/new_app .例如,将old_app/static/old_app重命名为new_app/static/new_app
  12. If you defined app config in apps.py;如果您在 apps.py 中定义了应用配置; rename those, and rename their references in settings.INSTALLED_APPS重命名它们,并在 settings.INSTALLED_APPS 中重命名它们的引用
  13. Delete migration files.删除迁移文件。
  14. Re-make migrations, and migrate.重新进行迁移,然后迁移。
  15. Load your table data from backups.从备份加载表数据。

If you use Pycharm , renaming an app is very easy with refactoring ( Shift + F6 default) for all project files.如果您使用Pycharm ,通过重构(默认为Shift + F6 )为所有项目文件重命名应用程序非常容易。
But make sure you delete the __pycache__ folders in the project directory & its sub-directories.但请确保删除项目目录及其子目录中的__pycache__文件夹。 Also be careful as it also renames comments too which you can exclude in the refactor preview window it will show you.还要小心,因为它也会重命名注释,您可以在它会显示的重构预览窗口中排除这些注释。
And you'll have to rename OldNameConfig(AppConfig): in apps.py of your renamed app in addition.此外,您还必须在重命名的应用程序的apps.py中重命名 OldNameConfig(AppConfig): 。

If you do not want to lose data of your database, you'll have to manually do it with query in database like the aforementioned answer.如果您不想丢失数据库的数据,则必须像上述答案一样在数据库中使用查询手动执行此操作。

Simple 4 steps to rename an existing app in Django project without any pain or data loss.在 Django 项目中重命名现有应用程序的简单 4 个步骤,没有任何痛苦或数据丢失。

Step 1步骤1

Rename the app folder.重命名应用程序文件夹。 For this example,"old_app" is our old name and "new_app" is our new name".对于本示例,“old_app”是我们的旧名称,“new_app”是我们的新名称”。

mv ./old_app ./new_app

Step 2第2步

Update all imports referencing the old folder to reference the new.更新所有引用旧文件夹的导入以引用新文件夹。

For example:例如:

# Before 
from myproject.old_app import models

# After
from myproject.new_app import models

Step 3第 3 步

Update old app name references within the Django migrations .更新Django 迁移中的旧应用名称引用。

Example changes you'll likely have to make:您可能需要进行的更改示例:

# 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'
)

Step 4第四步

Make a commit at this point.在这一点上进行提交。

Then, however you run your application migrations in a deployed environment, run django_rename_app before you run your migrations in that process.然后,无论您在已部署的环境中运行应用程序迁移,请在该过程中运行迁移之前运行django_rename_app

ie Before "python manage.py migrate --noinput", as the example below shows.即在“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

This will update the app name in the following internal Django database tables:这将更新以下内部 Django 数据库表中的应用程序名称:

  • django_content_type django_content_type
  • django_migrations django_migrations

And rename the prefix of all of your tables to start with your new app name, rather than the old one.并重命名所有表的前缀,以您的新应用程序名称开头,而不是旧名称。

That's it.就是这样。

Note : Its better to use your IDE's/text editor's find & replace function for making changes in the various files.注意:最好使用 IDE/文本编辑器的查找和替换功能对各种文件进行更改。

My simple alternative that avoids manual database manipulation (similar to https://stackoverflow.com/a/64133141/1608851 ), works well in a CI/CD, and is reversible.我的简单替代方案避免了手动数据库操作(类似于https://stackoverflow.com/a/64133141/1608851 ),在 CI/CD 中运行良好,并且是可逆的。

  1. Create an empty migration in the "old" app that renames the tables, content type, and migration records.在重命名表、内容类型和迁移记录的“旧”应用程序中创建一个空迁移。 Include a reverse migration.包括反向迁移。 Example:例子:
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)
    ]
  1. Set the model table name to the new_app.将 model 表名设置为 new_app。 Example:例子:
class ExampleModel(models.Model):

    # normal column definitions...

    class Meta:
        db_table = "newapp_examplemodel"  # add this line to the meta class

  1. Commit, test, and deploy the above changes.提交、测试和部署上述更改。
  2. Delete the migration created in step 1.删除在步骤 1 中创建的迁移。
  3. Rename/move the old app and fix all references (see https://stackoverflow.com/a/8408131/1608851 for more details), including references in migrations.重命名/移动旧应用程序并修复所有引用(有关更多详细信息,请参见https://stackoverflow.com/a/8408131/1608851 ),包括迁移中的引用。
  4. Remove the db_table overrides from the model meta classes.从 model 元类中删除db_table覆盖。
  5. Commit, test, and deploy.提交、测试和部署。

Notes:笔记:

  • The django_migrations table will retain a row with the old app, because that row is added after our new migration was run, but before it was registered under the new app name. django_migrations表将保留旧应用程序的一行,因为该行是我们的新迁移运行之后添加的,但在它以新应用程序名称注册之前添加。 It should be okay to leave that as is.保持原样应该没问题。
  • Deleting the migration is due to the above point, but also to prevent future issues when reverse migrating, but also because删除迁移是因为以上几点,也是为了防止以后反向迁移的时候出现问题,也是因为
  • Reversing this app rename requires checking out / deploying the commit from step 3, then reversing our migration, then checking out / deploying the commit before that撤消此应用程序重命名需要检出/部署第 3 步中的提交,然后撤消我们的迁移,然后在此之前检出/部署提交

Why not just use the option Find and Replace.为什么不直接使用“查找和替换”选项。 (every code editor has it)? (每个代码编辑器都有)?

For example Visual Studio Code (under Edit option):例如 Visual Studio Code(在编辑选项下):

Visual Studio Code 选项:“在文件中替换”

You just type in old name and new name and replace everyhting in the project with one click.您只需输入旧名称和新名称,然后一键替换项目中的所有内容。

NOTE : This renames only file content, NOT file and folder names.注意:这只会重命名文件内容,而不是文件和文件夹名称。 Do not forget renaming folders, eg.不要忘记重命名文件夹,例如。 templates/my_app_name/ rename it to templates/my_app_new_name/ templates/my_app_name/将其重命名为templates/my_app_new_name/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM