通过代理模型父代的继承模型字段来过滤代理模型。
问题描述:
我正在使用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
错误。
有没有像我提到的过滤方法? 谢谢!
答
正如我所提到的,这是因为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
我只是重写我的父母模型而不是替代的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')