我發現在將它傳遞給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」看起來不像是描述對象數據的名稱,而是像描述對象創建模式的名稱一樣,比內部的神祕開關更容易測試和維護子類。)
'do_something ()'做?可能有更好的方法來覆蓋'__init__'。 – Alasdair
您可以編寫自己的管理器並將'do_something()'重新放置到新的默認管理器中。 –
@Alasdair,是啊,我相信它會更好,我在[Django文檔](https://docs.djangoproject.com/en/1.11/ref/models/instances/)中讀到了這一點,它不是重寫'__init__'方法的好主意。但在這種情況下,它會將屬性添加到模型對象,應該在對象更改之前使用它。 '__init__'方法中的'do_something'位置確保了這一點。 –