Django 正确覆盖ModelForm';s表单字段,并将**KWARG从模型字段中保留

Django 正确覆盖ModelForm';s表单字段,并将**KWARG从模型字段中保留,django,django-models,django-forms,Django,Django Models,Django Forms,我的情况如下: class MyModel(models.Model): field 1 = models.CharField(kwarg1 = value1, kwarg2 = value2, ...) class MyCustomCharField(forms.CharField): def __init__(self, mandatarg1, ckwarg1 = cdefault1, ...): ... ... class MyModelForm(

我的情况如下:

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\u text=“blablabla”
max\u 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, ...)

但我有很多值可以像它一样复制,而且很难维护。。有什么想法吗?我有点疯狂,所以我真的很想找到一种干净的方法(如果不是太多的话)

你可以使用
**kwargs
捕获并传递所有你没有直接指定的关键字参数
kwargs
可以是任何名称,但惯例是使用该名称。情况如下:

def __init__(self, mandatarg1, ckwarg1=cdefault1, **kwargs)
    # do something
    super(MyCustomCharField, self).__init__(**kwargs)
    # do something else
由于双星号
**
,所有未明确定义的关键字参数将打包在名为
kwargs
dict
对象中。通过将
**kwargs
传递给对super的调用,在使用这些关键字参数调用super的
\uuuu init\uuuu
函数之前,这些值将再次解压缩

例如,您可以拨打以下电话:

field1 = MyCustomCharField(mandatvalue1, max_length=255, ckwarg1 = cvalue1)
kwargs
将如下所示:

kwargs = {'max_length': 255}
python将处理对super的调用,就像您调用:

super(MyCustomCharField, self).__init__(max_length=255)
对于带有一个星号的位置参数也可以这样做,惯例是使用
*args
这样做
args
将是位置参数的元组,与参数传递的顺序一致
*args
**kwargs
必须是函数定义中定义的最后一个参数。但是,您应该小心使用
*args
:请始终记住,在函数定义中,位置参数和关键字参数没有区别。因此,如果要扩展
多值字段
类,并且希望将字段作为位置参数传递,则必须将子类的
\uuuuu init\uuuu
方法中的每个参数都视为位置参数。因此:

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()))
如果只想指定关键字参数,或者想在super的位置参数之后指定位置参数,通常的方法是只指定
*args
**kwargs
作为参数:

def __init__(self, *args, **kwargs):
    keywordarg1 = kwargs.pop('keyword1', None)
    mandatorykeywordarg2 = kwargs.pop('keyword2')
    if len(args) == 2:
        # because tuples are immutable
        args = list(args)
        positionalargumentafterfields = args.pop(1)
    super(MyCustomMultiValueField, self).__init__(*args, **kwargs)
    # *args also works with a list
当您希望指定额外的参数,而其他一些代码依赖基类的位置参数来创建子类时,这是一个常见的用例。Django模型和表单是您希望这样做以防止破坏代码的示例


有关的文档。

您试图解决的实际问题是什么?
help\u文本是否未显示在模板中?我的问题仍然是检索Django的modelfield生成的默认参数,以将它们插入我的重写字段中。如果我得到了它们,我知道怎么做,但我不知道如何检索它们
super(MyCustomCharField,self)。\uu init\uu(**kwargs)
会处理好的。它将调用
CharField
(类的超类)
\uuuu init\uuu()
方法,其中包含所有您没有专门使用的关键字参数,该方法将处理所有默认功能,如指定字段的最大长度和帮助文本。