Django 1.7 - 具有自定义应用标签的模型发现和应用配置

Posted

技术标签:

【中文标题】Django 1.7 - 具有自定义应用标签的模型发现和应用配置【英文标题】:Django 1.7 - model discovery and application configs with custom app label 【发布时间】:2015-02-17 00:08:24 【问题描述】:

我目前正在使用Django==1.7.1。我有一些具有相同模块名称的可重用应用程序。这也使模型的应用程序标签相同。这实际上是矛盾的。您不能在 INSTALLED_APPSsettings 文件中的不同库中使用两个具有相同名称的模块。

我通过为模块添加AppConfig 解决了这个问题,并更改了它们的标签(app_label)以解决冲突;

#librarayX.my_module.apps.py
from django.apps import AppConfig


class ModuleAppConfig(AppConfig):
    name = 'libraryX.my_module'
    label = "X_my_module"
    verbose_name = "my_module"



#librarayY.my_module.apps.py
from django.apps import AppConfig


class ModuleAppConfig(AppConfig):
    name = 'libraryY.my_module'
    label = "Y_my_module"
    verbose_name = "my_module"


#settings.py

....
INSTALLED_APPS=[
    ...
   'libraryX.my_module.apps.ModuleAppConfig',
   'libraryY.my_module.apps.ModuleAppConfig',
    ...
]
...

现在,我可以将这些应用配置添加到我的 INSTALLED_APPS 而不是模块中。冲突刚刚解决。在那之前一切都很好。

这是我的问题;当我覆盖AppConfig 的标签时,Django 不会发现我在该模块中的模型。当我跑步时;

python manage.py makemigrations

似乎什么都没有改变。尽管我删除了所有迁移文件,但它甚至没有创建初始文件。我认为,它没有看到模型。每当我从我的应用程序配置中删除覆盖的标签字段时,模型就会再次被发现。所以,不要认为我的模型位置是错误的。

这也可能是错误,我不知道。但如果我做错了什么,会是什么?

谢谢!

【问题讨论】:

如果您认为这是一个错误,请在此处将其记录在 django 错误跟踪器上:code.djangoproject.com/newticket 有几个人正在积极致力于迁移错误修复,或者他们可能会指出您受支持的解决方案。 您确定该问题仅在您更改应用标签时才会出现吗?通常在 Django 1.7 中,如果您删除应用程序的所有迁移(和迁移目录),除非您明确给出其标签,否则 Django 不会为该应用程序创建新的迁移目录,例如python manage.py makemigrations Y_my_module,因此预计python manage.py makemigrations 不会为没有任何应用的应用创建初始迁移。 是的,我确定。即使我使用新的 app_label 运行它,它也会显示 No changes detected in app '.....'。当我进行一些迁移并覆盖 label 时,它还会创建一个迁移文件,该文件会删除我的所有模型。我敢肯定,它不会导入模型。我也在我的回答中描述了请看。 可能与1.8+的用户有关***.com/a/43014201/2586761 【参考方案1】:

我深入回顾了大部分Django 代码。 Django 不会导入在应用程序配置中定义了自定义应用程序标签的应用程序中的模型,正如问题中给出的那样。这是因为,即使您更改应用配置中的标签,模型 app_label 也不会更改。因此,Django 认为,模型和自定义应用程序配置适用于不同的应用程序。我认为,这是一个错误

django.apps.registry 中,populate method 中有几行是:

...
            # Load models.
            for app_config in self.app_configs.values():
                all_models = self.all_models[app_config.label]
                app_config.import_models(all_models)
...

这部分还应该导入app_config.name定义的模块中的模型,而不仅仅是app_config.label。因为,不会有应用标签与应用配置标签相同的模型。这是导致问题的有问题的部分之一。这还不够,还需要以某种方式更改模型app_label

解决方案:

这是我的解决方法。

我有一个抽象的应用配置,我的所有应用配置都将从中继承。

from collections import OrderedDict
from django.apps import AppConfig, apps


class BaseAppConfig(AppConfig):
    def __init__(self, *args, **kwargs):
        super(BaseAppConfig, self).__init__(*args, **kwargs)
        # Also import the models in modules defined in self.name
        mod_path, _, cls_name = self.name.rpartition('.')
        self.import_models(OrderedDict([(k, v) for k, v in apps.all_models[cls_name].iteritems() if self.name in v.__module__]))


    def import_models(self, all_models):
        if not self.models:
            # Set the model app_labels as self.label
            for m in all_models.values():
                m._meta.app_label = self.label
            super(BaseAppConfig, self).import_models(all_models)

这是一种不接触 Django 代码的解决方法。但是,我认为这个问题必须在 Django 中解决。模型 app_labels 也应根据应用配置中定义的 app_label 值进行更改。

【讨论】:

我现在没有时间检查这个分析,但你愿意把它作为一个错误提交到code.djangoproject.com/newticket 吗?如果您可以编写一个拉取请求,向 Django 的测试套件添加一个测试来演示该错误,那就更好了。 好的,我会创建一个票证,并在找到时尝试修补它。 嗨 Ahmet - 你有没有为这个问题创建过票? 你好@CarlMeyer,不幸的是我没有。在我看到你的最后评论并记住之后,我会打开它。但是我现在尝试了,我无法通过所有django 1.7 版本(0、1、2、3、4)的简单示例再次重现这种情况。我将在我的实际项目中检查有问题的部分并很快在那里进行测试,并根据该结果打开票证。

以上是关于Django 1.7 - 具有自定义应用标签的模型发现和应用配置的主要内容,如果未能解决你的问题,请参考以下文章

Django 1.7 迁移

如何在 Django 中测试自定义模板标签?

如何将自定义标签/过滤器添加到现有的 Django 应用程序?

无法在 Django 1.7 中创建 South 数据库模型

Django模型父链接的自定义相关名称?

Django - 创建自定义模板标签以显示模型名称