在我的应用模型中,我需要一种链接Problems
和Solutions
的方法 - 每个Problem
可以有多个Solutions
,而给定的Solution
可以映射回到多个Problems
。
Solution
是一个抽象基类,因为Solutions
可以有很多种。所以,我想我需要一个映射表ProblemSolutionMapping
,它使用GenericForeignKey
来容纳所有这些子类。但我正在试图弄清楚如何将类限制为Solutions
的子项,而不是整个应用程序中可用的所有类,这是当前正在发生的事情。
# Thanks to http://stackoverflow.com/a/23555691/1149759
class Solution(models.Model):
...
@classmethod
def get_subclasses(cls):
content_types = ContentType.objects.filter(app_label=cls._meta.app_label)
models = [ct.model_class() for ct in content_types]
return [model for model in models
if (model is not None and
issubclass(model, cls) and
model is not cls)]
class Meta:
abstract = True
class ProblemSolutionMapping(models.Model):
problem = models.ForeignKey(Problem)
content_type = models.ForeignKey(ContentType,
limit_choices_to=Solution.get_subclasses()) # <==== This is the issue
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
问题是,当我启动我的Django应用程序时,对ContentType.objects.filter(app_label=cls._meta.app_label)
的调用会引发错误:
django.core.exceptions.AppRegistryNotReady: Models aren't loaded yet.
不知道该怎么做 - 我尝试将映射表作为相关模型文件中的最后一个(所有子类都在同一个文件中定义在它上面),但它没有区别。 这是我必须进入管理表单的东西吗?或者在模型级别还有其他方法可以做到这一点吗?
(Django 1.9,如果重要的话。)
提前感谢您的帮助!
答案 0 :(得分:1)
django 1.7不再支持在导入期间重新生成模型。在加载所有应用程序后,您应该使用模型。所以你应该将列表静态传递给你的limit_choices_to 或使用Q对象,如下所示:
limit_choices_to=models.Q(app_label = 'app', model = 'a') | models.Q(app_label = 'app', model = 'b')
答案 1 :(得分:1)
所以我到了这里寻找答案。根据Mehran的帖子,我开发了类似于你的方法。相反,limit_choice_to
调用一个返回运行时创建的Q对象的方法。
下面是与你的get_subclasses类似的部分。
def get_subclasses(cls, *args, **kwargs):
for app_config in apps.get_app_configs():
for app_model in app_config.get_models():
model_classes = [c.__name__ for c in inspect.getmro(app_model)]
if cls.__name__ in model_classes:
yield app_model
这为我们创建了Q过滤器(在我的实现中,这只是一个没有附加到任何类的普通旧方法,但我认为它可能是):
def get_content_choices():
query_filter = None
for cls in Solution.get_subclasses():
app_label, model = cls._meta.label_lower.split('.')
current_filter = models.Q(app_label=app_label, model=model)
if query_filter is None:
query_filter = current_filter
else:
query_filter |= current_filter
return query_filter
最后,在我们的模型中:
class ProblemSolutionMapping(models.Model):
...
content_type = models.ForeignKey(ContentType, limit_choices_to=get_content_choices())
...