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

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

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


当前回答

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中更改应用程序的名称:

Rename the folder which is in your project root Change any references to your app in their dependencies, i.e. the app's views.py, urls.py , manage.py , and settings.py files. Edit the database table django_content_type with the following command: UPDATE django_content_type SET app_label='<NewAppName>' WHERE app_label='<OldAppName>' Also, if you have models, you will have to rename the model tables. For postgres, use ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName. For mysql too, I think it is the same (as mentioned by @null_radix). (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>'. Note: there is some debate (in comments) if this step is required for Django 1.8+; If someone knows for sure please update here. 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. For renaming django models, you'll need to change django_content_type.name entry in DB. For postgreSQL, use UPDATE django_content_type SET name='<newModelName>' where name='<oldModelName>' AND app_label='<OldAppName>' 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. Mentioned by @Serhii Kushchenko

元点(如果使用virtualenv):值得注意的是,如果您重命名包含virtualenv的目录,那么env中可能会有几个包含绝对路径的文件,也需要更新。如果你得到类似ImportError: No module named…这可能就是罪魁祸首。(感谢@danyamachine提供这篇文章)。

其他参考资料:你可能也想参考下面的链接,以获得更完整的图片:

用Django和South重命名应用 我如何将一个模型从一个django应用程序迁移到一个新的? 如何更改Django应用程序的名称? 使用Django South进行向后迁移 使用Django/South重命名模型的最简单方法? Python代码(感谢A.Raouf)来自动化上述步骤(未经测试的代码。我已经警告过你了!) Python代码(感谢rafaponieman)来自动化上述步骤(未经测试的代码。我已经警告过你了!)

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/

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

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

编辑运行/调试配置并更改环境变量DJANGO_SETTINGS_MODULE,因为它包含了您的项目名称。 进入Settings / Languages & Frameworks / Django,更新Settings文件的位置。

我的简单替代方案避免了手工数据库操作(类似于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覆盖。 提交、测试和部署。

注:

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. 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