2017-09-01 69 views
4

我有重寫__init__方法的模式是這樣的:傳遞參數__init__對象模型類的迭代查詢集

class MyModel(models.Model): 
    ... 

    def __init__(self, *args, **kwargs): 
     if not kwargs.get('skip', False): 
      do_something() 
     super().__init__(*args, **kwargs) 

如何傳遞skip參數__init__,當我ITER的查詢集:

data = [obj for obj in MyModel.objects.all()] 

我想通過法的自定義管理器來實現這一點,使用這個是這樣的:queryset.with_skip()

+0

'do_something ()'做?可能有更好的方法來覆蓋'__init__'。 – Alasdair

+0

您可以編寫自己的管理器並將'do_something()'重新放置到新的默認管理器中。 –

+0

@Alasdair,是啊,我相信它會更好,我在[Django文檔](https://docs.djangoproject.com/en/1.11/ref/models/instances/)中讀到了這一點,它不是重寫'__init__'方法的好主意。但在這種情況下,它會將屬性添加到模型對象,應該在對象更改之前使用它。 '__init__'方法中的'do_something'位置確保了這一點。 –

回答

2

我發現在將它傳遞給super().__init__之前,您不會從kwargs中刪除參數skip。這意味着「跳過」是一個字段的名稱,否則你得到異常TypeError("'skip' is an invalid keyword argument for this function")

如果你確實需要do_something(),那麼在使用之前必須先創建對象,以免任何人都忘記避免所有不支持的方式(??),然後自定義管理器等是不夠的。

你的問題是,models.Model.__init__(...)支持*args**kwargs參數非常完美,他們應該是可以互換的。你打破了它,如果「跳過」是由位置參數的完整元組傳遞的,那麼你就忽略它。那就是如果該對象是從數據庫創建的。閱讀文檔Customizing model loading

...如果模型的所有領域都存在,那麼值保證在__init__()預計的順序。也就是說,該實例可以通過cls(*values) ...
創建。
| @classmethod
| def from_db(cls, db, field_names, values):
| ...
| instance = cls(*values)
| ...

一個簡單的方法來解決它是調用do_something()super().__init__後,讀self.skip,而不是執行解析都kwargs和args。

def __init__(self, *args, **kwargs): 
     super().__init__(*args, **kwargs) 
     if not self.skip: 
      do_something() 

的一個問題可能是信號「post_init」那是在super().__init__結束時,如果你需要它發送。

最後一種可能性是支持*args(哈克,但仍然採用某種方式記錄名稱):

def __init__(self, *args, **kwargs): 
     if kwargs: 
      skip = kwargs.get('skip', False) 
     else: 
      # check "val is True" in order to skip if val is DEFERRED 
      skip = any(field.name == 'skip' and val is True 
         for val, field in zip(args, self._meta.concrete_fields) 
         ) 
     if not skip: 
      do_something() 
     super().__init__(*args, **kwargs) 

編輯:也許你就不需要你想要的東西和Proxy model,可以做一些事情有時通過基本模型對同一數據庫表中的相同數據進行額外處理是正確的解決方案。 (「Skip」看起來不像是描述對象數據的名稱,而是像描述對象創建模式的名稱一樣,比內部的神祕開關更容易測試和維護子類。)