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())
    ...