我的情况如下:
class MyModel(models.Model):
field 1 = models.CharField(kwarg1 = value1, kwarg2 = value2, ...)
class MyCustomCharField(forms.CharField):
def __init__(self, mandatarg1, ckwarg1 = cdefault1, ...):
...
...
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ['field1', ...]
field1 = MyCustomCharField(mandatvalue1, ckwarg1 = cvalue1, ...)
问题是:在我的表单中,我放弃了kwarg1 = default1, kwarg2 = default2, ...
,例如help_text="blablabla"
和max_length=255
。
有人想象一种保留这个默认参数的正确方法吗?
我试过了:
field1 = MyModel._meta.get_field('field1').formfield(form_class=MyCustomCharField, ckwarg1 = cvalue1)
它完美无缺,但是我无法传递mandatvalue1属性,所以我不能做我需要的事情!
还
field1 = MyCustomCharField(mandatvalue1, ckwarg1 = cvalue1, ..., **MyModel._meta.get_field('field1').__dict__)
但是在这里,我的词典中有太多的键,而Django崩溃了......
最后,我可以这样做:
field1 = MyCustomCharField(mandatvalue1, ckwarg1 = cvalue1, ..., help_text = MyModel._meta.get_field('field1').help_text, ...)
但我有很多值得像它一样复制,而且难以维护......有什么想法吗?我有点疯子,所以我真的很喜欢干净的方式(如果不是太多)
答案 0 :(得分:0)
您可以使用**kwargs
捕获并传递您未直接指定的所有关键字参数。 kwargs
可以是任何东西,但惯例是使用该名称。它看起来如下:
def __init__(self, mandatarg1, ckwarg1=cdefault1, **kwargs)
# do something
super(MyCustomCharField, self).__init__(**kwargs)
# do something else
由于双星号**
,未明确定义的所有关键字参数都将打包在名为dict
的{{1}}对象中。通过将kwargs
传递给super的调用,在使用这些关键字参数调用super **kwargs
函数之前,会再次解压缩这些值。
E.g。你可以拨打以下电话:
__init__
field1 = MyCustomCharField(mandatvalue1, max_length=255, ckwarg1 = cvalue1)
将如下所示:
kwargs
python将处理对super的调用,就像你调用了一样:
kwargs = {'max_length': 255}
对于具有单个星号的位置参数也可以这样做,惯例是使用super(MyCustomCharField, self).__init__(max_length=255)
执行此操作。 *args
将是位置参数的元组,与参数传递的顺序一致。 args
和*args
必须是函数定义中定义的最后一个参数。但是,您应该小心**kwargs
:始终记住,在函数定义中,位置参数和关键字参数没有区别。因此,如果要扩展*args
类,并且希望将字段作为位置参数传递,则必须将子类的MultiValueField
方法中的每个参数视为位置参数。所以:
__init__
如果您只想指定关键字参数,或者如果要在超级位置参数之后指定位置参数,则执行此操作的常用方法是仅指定class MyCustomMultiValueField(forms.MultiValueField):
def __init__(customarg1, customarg2=None, *args, **kwargs):
# do something
super(MyCustomMultiValueField, self).__init__(*args, **kwargs)
# this won't work, as now customargs2 is (BooleanField(), DateField()), instead of fields
MyCustomMultiValueField(1, (BooleanField(), DateField()))
# you can still pass fields as a keyword argument
MyCustomMultiValueField(1, fields=(BooleanField(), DateField()))
和*args
作为参数:
**kwargs
一个常见的用例是当你想要指定额外的参数时,而其他一些代码依赖于基类的位置参数来创建你的子类。 Django模型和表单是您希望这样做以防止破坏代码的示例。