Django GenericForeignKey限制继承自特定抽象模型的ContentType
在我的应用程序模型中,我需要一种链接Django GenericForeignKey限制继承自特定抽象模型的ContentType,django,django-models,Django,Django Models,在我的应用程序模型中,我需要一种链接问题和解决方案——每个问题都可以有多个解决方案,而给定的解决方案可以映射回多个问题 Solution是一个抽象基类,因为可以有多种解决方案。因此,我发现我需要一个映射表ProblemSolutionMapping,它使用GenericForeignKey来容纳所有这些子类。但我正在试图找出如何将类限制为解决方案的子类,而不是整个应用程序中可用的所有类,这就是目前正在发生的情况 # Thanks to http://stackoverflow.com/a/235
问题
和解决方案
——每个问题
都可以有多个解决方案
,而给定的解决方案
可以映射回多个问题
Solution
是一个抽象基类,因为可以有多种解决方案
。因此,我发现我需要一个映射表ProblemSolutionMapping
,它使用GenericForeignKey
来容纳所有这些子类。但我正在试图找出如何将类限制为解决方案
的子类,而不是整个应用程序中可用的所有类,这就是目前正在发生的情况
# 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 1.9,如有必要。)
提前感谢您的帮助 django 1.7不再支持在导入期间重新定义模型。您应该在加载所有应用程序后使用您的模型。因此,您应该静态地传递一个列表,以限制您的选择或使用Q对象,如下所示:
limit_choices_to=models.Q(app_label = 'app', model = 'a') | models.Q(app_label = 'app', model = 'b')
所以我来到这里寻找答案。基于Mehran的帖子,我开发了以下方法,与您的方法类似。相反,
limit\u choice\u to
调用一个返回运行时创建的Q对象的方法
下面是与get_子类类似的部分
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过滤器(在我的实现中,这只是一个普通的旧方法,没有附加到任何类,但我认为它可能是):
最后,在我们的模型中:
class ProblemSolutionMapping(models.Model):
...
content_type = models.ForeignKey(ContentType, limit_choices_to=get_content_choices())
...
问题是,我不能静态地将
解决方案
的子类处理方式的列表传递给限制\u选择\u到
bc。不过谢谢你。
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())
...