python - Django 1.7 - 带有自定义应用程序标签的模型发现和应用程序配置

标签 python django django-1.7 django-migrations

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

我通过为模块添加 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代码。在应用程序配置中定义了自定义应用程序标签的应用程序中的模型,正如问题中给出的那样,不会被 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 值进行更改。

关于python - Django 1.7 - 带有自定义应用程序标签的模型发现和应用程序配置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27542607/

相关文章:

python - 将 Django 模板设置从 1.7 更新到 1.8

python - 用于Python的带有C++的简单SWIG可以编译,但是输出似乎不正确?

python - 如何在 Ubuntu 上指定 Sqlite DB 的位置

Python:创建一个字典列表,其中键没有引号?

python - Django 1.7 : serve a pdf -file (UnicodeDecodeError)

django - 使用已填充的模型添加非空且唯一的字段

python - 使用 nosetests 随机化测试执行顺序

python - 在 Fedora 24 上为 Python 3 安装 OpenCV

django - 为什么模型字段验证发生在 validate 或 validate_<field> 被调用之前?

python - Django - MultiValueField 实现