ModelForm fields order inaffected?

142 views Asked by At

trying to alter order of fields in admin ModelForm. Bellow is my attempt, however order is kept unchanged. Added fields oi_number and vat_number are rendered at the end besides they are not at the end in self.fields SortedDict dictionary.

class ContactAdminForm(forms.ModelForm):
    oi_number = fields_for_model(OrganizationExtra)['oi_number']
    vat_number = fields_for_model(OrganizationExtra)['vat_number']
    # fields = ('organization', 'oi_number', 'vat_number')
    # ^^^ this won't affect fields order either

    class Meta:
        model = Organization

    def __init__(self, *args, **kwargs):
        super(ContactAdminForm, self).__init__(*args, **kwargs)
        try:
            org_ix = self.fields.keyOrder.index('organization')
            self.fields.keyOrder.insert(org_ix+1, self.fields.keyOrder[-2])
            self.fields.keyOrder.insert(org_ix+2, self.fields.keyOrder[-1])
            del self.fields.keyOrder[-2:]
        except ValueError:
            pass

Does get the order of fields resolved before __init__ method is called ? How can I change their order ?

Update: The above ModelForm is used as a form in admin model which defines its own fields, so if I put all fields definition in above form, I'll get FieldError exception about unknown field name:

class ContactAdminForm(forms.ModelForm):
    ...
    class Meta:
        model = Organization
        fields = ('organization', 'oi_number', 'vat_number')

class ContactOptionsEx(ContactOptions):
    form = ContactAdminForm

admin.site.register(Contact, ContactOptionsEx)

# at attempt to render the form:
# FieldError at /admin/contact/contact/3/
# Unknown field(s) (organization) specified for Organization

However the field named organization does exist and is available in ContactAdminForm.__init__ method.

1

There are 1 answers

3
sk1p On

The error

Unknown field(s) (organization) specified for Organization

does not refer to a field on your form, but to a field on the model (Organization).

I think the problem here is that you are trying to add fields from a different Model (OrganizationExtra) to the ModelForm for Organization. There is always a one-to-one relation between a ModelForm and a Model. If you want to edit a related instance in the admin, you can use inlines:

class OrganizationExtraInline(admin.StackedInline):
    model = OrganizationExtra

class ContactOptionsEx(ContactOptions):
    inlines = ContactOptions.inlines + [OrganizationExtraInline]
    # ...

If you want to limit the inline to one instance, use a OneToOneField or max_num = 1