Django forms, inheritance and order of form fields

前端 未结 11 1763
终归单人心
终归单人心 2020-12-12 12:15

I\'m using Django forms in my website and would like to control the order of the fields.

Here\'s how I define my forms:

class edit_form(forms.Form):
         


        
11条回答
  •  北海茫月
    2020-12-12 12:53

    The above answers are right but incomplete. They only work if all the fields are defined as class variables. What about dynamic form fields which have to be defined in the intitialiser (__init__)?

    from django import forms
    
    class MyForm(forms.Form):
        field1 = ...
        field2 = ...
    
        field_order = ['val', 'field1', 'field2']
    
        def __init__(self, val_list, *args, **kwargs):
            super(MyForm, self).__init__(*args, **kwargs)
            vals = zip(val_list, val_list)
            self.fields['val'] = forms.CharField(choices=vals)
    

    The above will never work for val but will work for field1 and field2 (if we reorder them). You might want to try defining field_order in the initialiser:

    class MyForm(forms.Form):
        # other fields
    
        def __init__(self, val_list, *args, **kwargs):
            super(MyForm, self).__init__(*args, **kwargs)
            vals = zip(val_list, val_list)
            self.fields['val'] = forms.CharField(choices=vals)
            self.field_order = ['val', 'field1', 'field2']
    

    but this will also fail because the field order is fixed before the call to super().

    Therefore the only solution is the constructor (__new__) and set field_order to a class variable.

    class MyForm(forms.Form):
        # other fields
    
        field_order = ['val', 'field1', 'field2']
    
        def __new__(cls, val_list, *args, **kwargs):
            form = super(MyForm, cls).__new__(cls)
            vals = zip(val_list, val_list)
            form.base_fields['val'] = forms.CharField(choices=vals)
            return form
    

提交回复
热议问题