我在Django中通过重命名应用程序的文件夹、导入和所有引用(模板/索引)来更改应用程序的名称。但现在,当我尝试运行python manage.py runserver时,我得到了这个错误:
Error: Could not import settings 'nameofmynewapp.settings' (Is it on sys.path?): No module named settings
我该如何调试和解决这个错误?有什么线索吗?
按照以下步骤在Django中更改应用程序名称:
views.py、urls.py、manage.py 和 settings.py 文件。django_content_type:UPDATE django_content_type SET app_label='<NewAppName>' WHERE app_label='<OldAppName>'ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName。对于 mysql,我认为是相同的(由 @null_radix 提到)。django_migrations 表以避免重新运行之前的迁移:UPDATE django_migrations SET app='<NewAppName>' WHERE app='<OldAppName>'。注意:在评论中有一些争议,是否需要执行此步骤来适用于 Django 1.8+;如果有人确定,请在此处更新。models.py 的 Meta 类列出了 app_name,请确保也将其重命名(由 @will 提到)。static 或 templates 文件夹设置了命名空间,则还需要将这些文件夹重命名。例如,将 old_app/static/old_app 重命名为 new_app/static/new_app。models,您需要更改 DB 中的 django_content_type.name 条目。对于 postgreSQL,请使用 UPDATE django_content_type SET name='<newModelName>' where name='<oldModelName>' AND app_label='<OldAppName>'__pycache__/ 文件夹,否则会出现 EOFError: marshal data too short when trying to run the server。由 @Serhii Kushchenko 提到元点(如果使用virtualenv): 值得注意的是,如果您正在重命名包含虚拟环境的目录,则可能会有几个文件在您的环境中包含绝对路径,并且还需要更新。如果您遇到诸如ImportError: No module named ...等错误,这可能是罪魁祸首。(感谢@danyamachine提供此信息)。
其他参考资料: 您可能还想参考以下链接以获得更完整的图片:
ALTER TABLE <oldAppName>_modelName RENAME TO <newAppName>_modelName。 - null_radixALTER SEQUENCE <oldAppName>_<modelName>_<PK>_seq RENAME TO <newAppName>_<modelName>_<PK>_seq;。尽管这并非必要,但是系统本身并不关心名称。列 DEFAULT 存储了一个 OID ('foo_pkey_seq'::regclass),你可以更改序列名称而不会破坏它 - OID 保持不变。 - Konstantine KalbazovDjango 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/
有趣的问题!我很快就要重新命名许多应用程序,所以我进行了一次干运行。
这种方法允许通过原子步骤进行进展,以最小化重命名的应用程序上工作的其他开发人员的干扰。
请参见本答案底部的链接,获取可工作的示例代码。
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。
makemigrations 命令以生成与数据库表一致的新迁移文件。@meshy。但是,您仍然很好地解决了这个问题。谢谢你。 - Rohan如果您正在使用PyCharm,并且在重命名后项目停止工作:
使用所需的名称启动一个新应用程序,并将所有代码从原始应用程序复制到其中。确保在新复制的代码中修复命名空间以匹配新的应用程序名称。
makemigrations和migrate。注意:如果该应用程序有许多外键,则在尝试运行复制应用程序的初始迁移时,可能会出现冲突的反向访问器问题。您必须重命名旧应用程序上的related_name访问器(或添加新的)以解决冲突。
创建数据迁移,将原始应用程序表中的相关数据复制到新应用程序表中,然后再次migrate。
目前为止,一切仍然正常,因为原始应用及其数据仍在原地。
现在,您可以重构所有依赖于原始应用的代码,使其仅使用新应用。查看其他答案以了解要注意的示例。
确认一切正常后,可以删除原始应用程序。这涉及另一个(模式)迁移。
这样做的好处是每个步骤都使用正常的Django迁移机制,无需手动操作数据库,而且我们可以在源代码控制中跟踪所有内容。此外,我们保留原始应用及其数据,直到确信一切正常。
apps.get_model()不会引起问题。相反,这就是它的作用:apps.get_model()返回一个“伪”模型,从迁移历史记录中构建而成。在迁移历史记录的那个点上,该应用程序仍然存在。请参见文档此处和此处。 - djvg重新迁移的方法可以使代码更加清晰。但是,如果其他应用程序使用外键指向需要重命名的应用程序的模型,则需要进行检查并确保其迁移文件不包含此迁移。
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中的Meta类列出了app_name,请确保也将其重命名(由@will提到)。static或templates文件夹的名称空间,则还需要将其重命名。例如,将old_app/static/old_app重命名为new_app/static/new_app。简单的4个步骤,无需痛苦或数据丢失即可在Django项目中重命名现有应用程序。
第一步
重命名应用程序文件夹。例如,"old_app"是我们的旧名称,"new_app"是我们的新名称。
mv ./old_app ./new_app
第二步
更新所有引用旧文件夹的导入以引用新文件夹。
例如:
# Before
from myproject.old_app import models
# After
from myproject.new_app import models
第三步
在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数据库表中更新应用程序名称:
并将所有表的前缀重命名为以新应用程序名称开头,而不是旧名称。
就这样。
注意:最好使用IDE/文本编辑器的查找和替换功能来更改各个文件。
如果您使用 Pycharm,则通过 重构(默认键为Shift+F6)更改应用程序名称非常容易,适用于所有项目文件。
但请确保删除项目目录及其子目录中的__pycache__文件夹。此外要注意,它还会更改注释的名称,您可以在重构预览窗口中排除注释名称。
此外,您还需要在重命名后的应用的 apps.py 文件中将 OldNameConfig(AppConfig) 也进行重命名。
如果您不想丢失数据库数据,则必须手动使用数据库查询执行上述操作。
我的简单替代方案避免了手动数据库操作(类似于https://dev59.com/G2oy5IYBdhLWcg3wo_vo#64133141),在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
db_table覆盖。注:
django_migrations表将保留具有旧应用程序的行,因为该行是在我们运行新迁移之后但在其在新应用程序名称下注册之前添加的。可以将其保留不变。现在您可以使用django-rename-app工具。
INSTALLED_APPS设置中python manage.py rename_app old_app new_app有关详细的说明,请访问:
pip install django-rename-app安装该库,然后运行python manage.py rename_app <old_app_name> <new_app_name>命令来重命名应用程序。具体细节请访问 https://github.com/odwyersoftware/django-rename-app。 - Kwaku Biney