开发者

How can I subclass a modelform (extend with extra fields from the model)?

开发者 https://www.devze.com 2023-03-16 19:19 出处:网络
I have a model and a form: class MyModel(models.Model): field_foo = models.CharField(_(\"Foo\"), max_length=50)

I have a model and a form:

class MyModel(models.Model):
    field_foo = models.CharField(_("Foo"), max_length=50)
    field_bar = models.IntegerField(_("Bar"))

class MyFormOne(forms.ModelForm):
    class Meta:
        model=MyMod开发者_如何学Goel
        fields = ('field_foo', )
        widgets = {'field_foo': forms.TextInput(attrs={'size': 10, 'maxlength': 50}),}

I would like to have another form MyFormTwo which would subclass that form by including also the field field_bar. My point is not to have to repeat the widget declaration for field_foo in the second form (DRY principle), and also not to have to repeat the list of fields from MyFormOne (in reality there are much more then one field then in the simple example above).

How should I define MyFormTwo?


You shouldn't have to explicitly declare the entire widget, just modify the attrs which are different. Or if you have custom widgets in the real code, I would either

  1. Create a custom model field class as well which uses that widget by default, if it's a general condition, so in the form class it just works "automagically".
  2. If it's just form specific (not model specific), then for that case I'd just declare the form field explicitly on Form class, not in Meta and then inheritance applies in a straightforward way.

But with default widgets (with custom attrs) I'd try something like the following

class MyModel(models.Model):
    field_foo = models.CharField(_("Foo"), max_length=50)
    field_bar = models.IntegerField(_("Bar"))

class MyFormOne(forms.ModelForm):
    class Meta:
        model=MyModel
        fields = ('field_foo', )

    def __init__(*args, **kwargs):
        super(MyFormOne, self).__init__(*args, **kwargs)

        self.fields['field_foo'].widget.attrs['size'] = 10
        # max_length should already be set automatically from model
        # TextInput is also default widget for CharField

class MyFormTwo(MyFormOne):
    class Meta:
        model=MyModel
        fields = MyFormOne.Meta.fields + ('field_foo2',)

    def __init__(*args, **kwargs):
        super(MyFormTwo, self).__init__(*args, **kwargs)

        self.fields['field_foo2'].widget.attrs['size'] = 10


I'm not sure if this will work or not (it's completely untested with Django forms/models), but if it does let me know.

class MyModel(models.Model):
    field_foo = models.CharField(_("Foo"), max_length=50)
    field_bar = models.IntegerField(_("Bar"))

class MyFormOne(forms.ModelForm):
    class Meta:
        model=MyModel
        fields = ('field_foo', )
        widgets = {'field_foo': forms.TextInput(attrs={'size': 10, 'maxlength': 50}),}

class MyFormTwo(MyFormOne):
    class Meta(MyFormOne.Meta):
        fields = MyFormOne.Meta.fields + ('field_foo2',)
        widgets = MyFormOne.Meta.widgets
        # Add new fields as a dictionary
        widgets.update({'field_foo2': forms.TextInput(attrs={'size': 10, 'maxlength': 50}),)
        # Or add them one by one
        widgets['field_foo3'] = forms.TextInput(attrs={'size': 10, 'maxlength': 50})

Again, I have no idea if that will help you. Please let me know what results you get.


This snippet is a bit old, but it explains the only way I've ever been able to get form multiple inheritance to work. It's pretty ugly.

http://djangosnippets.org/snippets/703/

There is also an open ticket regarding it: https://code.djangoproject.com/ticket/7018

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号