[英]How to create a django model field mixin
我正在嘗試為模型字段(而不是表單字段)創建通用mixin,mixin的init采用命名參數。 我遇到麻煩用另一個類實例化mixin。
這是代碼
class MyMixin(object):
def __init__(self, new_arg=None, *args, **kwargs):
super(MyMixin, self).__init__(*args, **kwargs)
print self.__class__, new_arg
class MyMixinCharField(MyMixin, models.CharField):
pass
...
class MyMixinModelTest(models.Model):
myfield = MyMixinCharField(max_length=512,new_arg="myarg")
對此模型進行遷移會產生以下輸出:
<class 'myapp.mixintest.fields.MyMixinCharField'> myarg
<class 'myapp.mixintest.fields.MyMixinCharField'> None
<class 'myapp.mixintest.fields.MyMixinCharField'> None
Migrations for 'mixintest':
0001_initial.py:
- Create model MyMixinModelTest
首先,為什么init運行3次? 在第二個兩個中,kwarg'new_arg'在哪里? 如何為django創建字段mixin?
編輯:與另一個問題相反,這個問題詢問場混合,相關問題是指模型混合。
首先,為什么init運行3次?
雖然models.py
只導入一次,但是在其中創建了Field
對象,例如......
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
...多次克隆,包括使用最初創建的關鍵字args調用字段構造函數。 您可以使用traceback
模塊查看它發生的位置......
import traceback
class MyMixin(object):
def __init__(self, new_arg=None, *args, **kwargs):
super(MyMixin, self).__init__(*args, **kwargs)
print self.__class__, new_arg
traceback.print_stack()
...在輸出中顯示以下幾次...
File "django/db/migrations/state.py", line 393, in from_model
fields.append((name, field.clone()))
File "django/db/models/fields/__init__.py", line 464, in clone
return self.__class__(*args, **kwargs)
File "myproj/myapp/models.py", line 11, in __init__
traceback.print_stack()
在第二個兩個中,kwarg'new_arg'在哪里?
當你最初打電話給...
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
... "myarg"
作為new_arg
參數傳遞給...
def __init__(self, new_arg=None, *args, **kwargs):
...但是因為你沒有將該參數傳遞給基礎的Field
構造函數...
super(MyMixin, self).__init__(*args, **kwargs)
...它沒有存儲在底層Field
對象的任何位置,因此當克隆該字段時, new_arg
參數不會傳遞給構造函數。
但是,將該選項傳遞給超類構造函數將不起作用,因為CharField
不支持該關鍵字arg,因此您將獲得...
File "myproj/myapp/models.py", line 29, in MyMixinModelTest
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
File "myproj/myapp/models.py", line 25, in __init__
super(MyMixinCharField, self).__init__(*args, **kwargs)
File "django/db/models/fields/__init__.py", line 1072, in __init__
super(CharField, self).__init__(*args, **kwargs)
TypeError: __init__() got an unexpected keyword argument 'new_arg'
如何為django創建字段mixin?
由於這種克隆行為,如果要添加自定義字段選項,則必須定義自定義deconstruct()
方法,以便Django可以序列化您的新選項...
class MyMixin(object):
def __init__(self, new_arg=None, *args, **kwargs):
super(MyMixin, self).__init__(*args, **kwargs)
self.new_arg = new_arg
print self.__class__, new_arg
def deconstruct(self):
name, path, args, kwargs = super(MyMixin, self).deconstruct()
kwargs['new_arg'] = self.new_arg
return name, path, args, kwargs
class MyMixinCharField(MyMixin, models.CharField):
pass
class MyMixinModelTest(models.Model):
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
...輸出......
<class 'myapp.models.MyMixinCharField'> myarg
<class 'myapp.models.MyMixinCharField'> myarg
<class 'myapp.models.MyMixinCharField'> myarg
所以我經過大量的修補和重新閱讀自定義模型字段上的django文檔后想出來你需要一個解構函數和你的init。 Django字段需要一個deconstruct
方法來序列化。
mixin也應該有這個方法:
class MyMixin(object):
def __init__(self, new_arg=None, *args, **kwargs):
self.new_arg = new_arg
super(MyMixin, self).__init__(*args, **kwargs)
def deconstruct(self):
name, path, args, kwargs = super(MyMixin, self).deconstruct()
if self.new_arg is not None:
kwargs['new_arg'] = self.new_arg
return name, path, args, kwargs
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.