如何覆盖Django的apps.py和AppConfig以用于第三方应用程序(如果不存在)?

4
自Django 1.7以来,新增了AppConfig功能,建议将post_migrate信号放在其自定义实现的ready()部分中 - https://docs.djangoproject.com/en/stable/ref/signals/#post-migrate 文档中描述实现AppConfig的基本方式是在__init__.py文件中使用default_app_config设置指向它。文档还建议一种覆盖任何应用程序现有AppConfig的方法:https://docs.djangoproject.com/en/stable/ref/applications/#for-application-users 我研究了一下,发现Django实际上会为INSTALLED_APPS中的每个应用程序创建一个AppConfig实例,即使其自定义实现未实现,它也会为您引导默认值。
我的问题是,如何为不实现AppConfig(最简单的示例是没有apps.py的第三方包)的应用程序提供具有post_migrate信号的自定义应用程序配置?
我知道即使对于这个应用程序,Django也会创建默认版本的AppConfig,但我应该在哪里以及如何告诉它不要这样做,而是使用我的自定义AppConfig,并重写ready()方法实现添加post_migrate
3个回答

7
假设您希望为安装在虚拟环境中的Django Crispy Forms创建自定义的AppConfig。请按以下步骤操作:
步骤1:在项目中创建名为crispy_forms的文件夹。 步骤2:在该文件夹中创建一个__init__.py文件,并粘贴以下内容。
from django.apps import AppConfig

default_app_config = 'crispy_forms.apps.MyAppConfig'

步骤三:在crispy_forms文件夹中创建一个apps.py文件,并复制粘贴以下内容

from django.apps import AppConfig

class MyAppConfig(AppConfig):

    verbose_name = 'customized crispy_forms'
    name = "crispy_forms"

    def __init__(self, app_name, app_module):
        AppConfig.__init__(self,app_name, app_module)
        print 'My app config', app_name, app_module

如果 Django 没有重新加载类,请重新启动开发服务器,然后您会看到类似于以下内容的东西:
My app config crispy_forms <module 'crispy_forms' from '/home/xxx/project/crispy_forms/__init__.pyc'>

好建议!谢谢你!但在这种情况下,我开始收到来自我的应用程序其他部分的错误。错误上下文基本上如下所示:from crispy_forms.models import SomeModel ImportError: No module named 'crispy_forms.models' - canufeel
好的观察!在发布这篇文章之前,我实际上没有尝试从crispy_forms应用程序导入。会尽快查看。 - e4c5
1
看起来,如果我们保持 name =“crispy_forms”,Django 将认为这个新的自定义应用程序是 crispy_forms 的重写,然后当我们尝试从初始的 crispy_forms 插件导入任何内容时,它会尝试从我们的应用程序中导入。只要我们使用相同的名称,INSTALLED_APPS 中的 crispy_forms 就会开始指向我们的应用程序,并具有自定义的 AppConfing - canufeel

1
我尝试了其他建议,但它们对我没用。但是官方文档起作用了。解决方案非常简单:适用于应用程序用户 引用手册:
如果您在名为“文集”的项目中使用“摇滚乐”,但您希望它显示为“爵士曼纳乔” ,则可以提供自己的配置:
# anthology/apps.py

from rock_n_roll.apps import RockNRollConfig

class JazzManoucheConfig(RockNRollConfig):
    verbose_name = "Jazz Manouche"

# anthology/settings.py

INSTALLED_APPS = [
    'anthology.apps.JazzManoucheConfig',
    # ...
]

1
我的问题与这里的答案相似,帮助我找到了解决方案。我在我的Django应用程序中使用 "django-constance" 依赖项来管理一些应用程序参数,以便在管理站点内部设置。但是,我想确保一些参数在使用我的Web应用程序时立即设置为常量。
不幸的是,@canufeel提供的解决方案没有起作用,我无法在我的应用程序中使用constance子包,出现了“导入错误”。
这就是我做的方式:
我在我的应用程序下创建了一个名为“myApp/constance”的子包,在其中定义了与@canufeel提到的相同的内容。但是主要变化是我不再在INSTALLED_APPS中导入“constance”包,而是导入“myapp.constance”,在那里我可以像这样覆盖设置:
MYAPP_CONSTANCE_CONFIG_VAR = {
'ACCOUNT_ACTIVATION_DAYS': (7, 'Number of days before activation is kept available'),
'BOOTSTRAP_THEME': ('slate', 'Bootstrap theme for front end', 'select_theme'),
...
}

然后覆盖:
BASE_CONSTANCE_CONFIG = getattr(settings, 'CONSTANCE_CONFIG', {})
BASE_CONSTANCE_CONFIG.update(MYAPP_CONSTANCE_CONFIG_VAR)

settings.CONSTANCE_CONFIG = BASE_CONSTANCE_CONFIG_VAR
settings.CONSTANCE_ADDITIONAL_FIELDS = BASE_CONSTANCE_ADDITIONAL_FIELDS
settings.CONSTANCE_CONFIG_FIELDSETS = WAVES_CONSTANCE_CONFIG_FIELDSETS

那就可以解决问题,但我认为这不是最先进的解决方案 :-)

注意:如果多个应用程序需要更新常量配置,则此解决方案可能无法正常工作... - marcoooo
在我的项目中,我只需要添加一个名为“myapp_constance.py”的文件到我的应用程序中,并将其包含在我的__init__.py中即可... 工作完成,实际上非常容易 :-) - marcoooo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接