【问题标题】:Filter on the proxy model by field of inherited model of the proxy models parent.按代理模型父代的继承模型字段过滤代理模型。
【发布时间】:2014-09-01 09:04:36
【问题描述】:

我正在使用Django 1.6 并使用模型继承。标题可能比较混乱,下面是解释;

class ParentModel(models.Model)
    class Meta:
        db_table = "parent_model"

    my_field=.....

class ProxyModelOfParentModel(ParentModel)
    class Meta:
        proxy=True

    objects=CustomManager()


class InheritedModel(ParentModel)
    class Meta:
        db_table = "inherited_model"

    my_extra_field=.....

假设,这些是我们的模型。当我尝试在 ParentModel 上按 my_extra_field 过滤时,我会这样做;

ParentModel.objects.filter(inheritedmodel__my_extra_field='test')

但是,我想过滤代理模型,比如;

ProxyModelOfParentModel.objects.filter(inheritedmodel__my_extra_field='test')

当我运行它时,它将无法在代理模型中找到字段 inheritedmodel。这也可能是 Django 中的错误,我不知道。不知何故,当我尝试过滤代理模型时,django 现在确实正确构建了查询集。

我使用代理模型而不是父模型的原因是,在不同的管理员中使用代理模型。当我在管理员list_filter 中输入密钥时,我遇到了FieldDoesNotExists 错误。

有没有我提到的过滤方法? 谢谢!

【问题讨论】:

    标签: python django


    【解决方案1】:

    正如我所提到的,这是因为代理模型初始化的 django 实现。我不知道,这是否是错误,但我需要以某种方式解决这个问题。我发现这是因为模型_meta初始化的一部分。 django.db.models.options.py 中的这部分是我注释掉的部分导致了这个问题

    def _fill_related_objects_cache(self):
        cache = SortedDict()
        parent_list = self.get_parent_list()
        for parent in self.parents:
            for obj, model in parent._meta.get_all_related_objects_with_model(include_hidden=True):
                #THIS PART WAS CAUSING THE PROBLEM
                # if (obj.field.creation_counter < 0 or obj.field.rel.parent_link) and obj.model not in parent_list:
                #     continue
                if not model:
                    cache[obj] = parent
                else:
                    cache[obj] = model
        # Collect also objects which are in relation to some proxy child/parent of self.
        proxy_cache = cache.copy()
        for klass in get_models(include_auto_created=True, only_installed=False):
            if not klass._meta.swapped:
                for f in klass._meta.local_fields:
                    if f.rel and not isinstance(f.rel.to, six.string_types) and f.generate_reverse_relation:
                        if self == f.rel.to._meta:
                            cache[f.related] = None
                            proxy_cache[f.related] = None
                        elif self.concrete_model == f.rel.to._meta.concrete_model:
                            proxy_cache[f.related] = None
        self._related_objects_cache = cache
        self._related_objects_proxy_cache = proxy_cache
    

    我只是覆盖了父模型的 Options 类和元类,而不是像覆盖 Django 本身一样;

    class CustomProxyModelOptions(Options):
        def _fill_related_objects_cache(self):
            cache = SortedDict()
            parent_list = self.get_parent_list()
            for parent in self.parents:
                for obj, model in parent._meta.get_all_related_objects_with_model(include_hidden=True):
                    if not model:
                        cache[obj] = parent
                    else:
                        cache[obj] = model
            # Collect also objects which are in relation to some proxy child/parent of self.
            proxy_cache = cache.copy()
            for klass in get_models(include_auto_created=True, only_installed=False):
                if not klass._meta.swapped:
                    for f in klass._meta.local_fields:
                        if f.rel and not isinstance(f.rel.to, six.string_types) and f.generate_reverse_relation:
                            if self == f.rel.to._meta:
                                cache[f.related] = None
                                proxy_cache[f.related] = None
                            elif self.concrete_model == f.rel.to._meta.concrete_model:
                                proxy_cache[f.related] = None
            self._related_objects_cache = cache
            self._related_objects_proxy_cache = proxy_cache
    
    
    class ProxyModelMeta(ModelBase):
        def __new__(cls, *args, **kwargs):
            model = super(ProxyModelMeta, cls).__new__(cls, *args, **kwargs)
            model._meta.__class__ = CustomProxyModelOptions
            return model
    
    class ParentModel(models.Model)
        class Meta:
            db_table = "parent_model"
    
        my_field=.....
    
    class ProxyModelOfParentModel(ParentModel)
        __metaclass__= ProxyModelMeta
        class Meta:
            proxy=True
    
        objects=CustomManager()
    
    
    class InheritedModel(ParentModel)
        class Meta:
            db_table = "inherited_model"
    
        my_extra_field=.....
    

    现在,我可以过滤了;

    ProxyModelOfParentModel.objects.filter(inheritedmodel__my_extra_field='test')
    

    【讨论】:

      猜你喜欢
      • 2022-06-24
      • 1970-01-01
      • 2013-04-08
      • 1970-01-01
      • 2019-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多