2014-09-01 72 views
0

我正在使用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錯誤。

有沒有像我提到的過濾方法? 謝謝!

回答

0

正如我所提到的,這是因爲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')