我正在尝试为模型字段(而不是表单字段)创建通用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")
Run Code Online (Sandbox Code Playgroud)
对此模型进行迁移会产生以下输出:
<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
Run Code Online (Sandbox Code Playgroud)
首先,为什么init运行3次?在第二个两个中,kwarg'new_arg'在哪里?如何为django创建字段mixin?
编辑:与另一个问题相反,这个问题询问场混合,相关问题是指模型混合.
首先,为什么init运行了3次?
虽然models.py
只导入一次,但Field
其中创建的对象,例如...
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
Run Code Online (Sandbox Code Playgroud)
...被克隆多次,其中涉及使用最初创建它们的关键字 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()
Run Code Online (Sandbox Code Playgroud)
...在输出中多次显示以下内容...
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()
Run Code Online (Sandbox Code Playgroud)
后两个中的 kwarg 'new_arg' 在哪里?
当你最初打电话...
myfield = MyMixinCharField(max_length=512, new_arg="myarg")
Run Code Online (Sandbox Code Playgroud)
..."myarg"
作为参数传递给new_arg
...
def __init__(self, new_arg=None, *args, **kwargs):
Run Code Online (Sandbox Code Playgroud)
...但是因为您没有将该参数传递给底层Field
构造函数...
super(MyMixin, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)
...它没有存储在底层的任何地方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'
Run Code Online (Sandbox Code Playgroud)
如何为 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")
Run Code Online (Sandbox Code Playgroud)
...输出...
<class 'myapp.models.MyMixinCharField'> myarg
<class 'myapp.models.MyMixinCharField'> myarg
<class 'myapp.models.MyMixinCharField'> myarg
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1546 次 |
最近记录: |