pdxMobile
pdxMobile

Reputation: 105

Reorder modelform fields

I need to reorder the fields in a modelform that came from another base class. Couldn't find a solution to that. "Address" in the snippet below always show up at the beginning in the HTML template. How can I move it further down with the rendered template? Thanks in advance.

class Address:
   street= ...
   city= ...

class Customer(Address):
   name = ...
   ...

class CustomerForm(ModelForm):
   def __init__(...)
        super(CustomerForm, self).__init__(*args, **kw)
        self.fields.keyOrder=[
        'name',
        'Address',  #<-- I want "Address" appear after the name in my template
                    #<-- This obviously is not the right code.
   class Meta:
      model = Customer

-P

Upvotes: 7

Views: 6391

Answers (5)

Leandro Regueiro
Leandro Regueiro

Reputation: 11

In newer Django the fields attribute is a collections.OrderedDict which since Python 3.2 has a new method move_to_end, so you can simply:

class CustomForm(forms.Form):

    ...

    # Note the following must contain all the fields in the form in the order
    # you desire.
    CUSTOM_ORDER = ('field1', 'field2', 'field3')

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

        # Use custom order for form fields.
        for field_name in CUSTOM_ORDER:
            self.fields.move_to_end(field_name)

Upvotes: 1

Algor
Algor

Reputation: 101

In Django 1.9 they add new argument to Form class Now you can change the order by defining field_order for example adding two fields to userena application form:

class SignupFormExtra(SignupForm):
    """
    A form to demonstrate how to add extra fields to the signup form, in this
    case adding the first and last name.
    """
    first_name = forms.CharField(label=_(u'First name'),
                             max_length=30,
                             required=False)

    last_name = forms.CharField(label=_(u'Last name'),
                            max_length=30,
                            required=False)
    field_order=['first_name','last_name']

You can use it to any form that inherit class Form.

By default Form.field_order=None, which retains the order in which you define the fields in your form class. If field_order is a list of field names, the fields are ordered as specified by the list and remaining fields are appended according to the default order.

Upvotes: 10

brucegarro
brucegarro

Reputation: 61

from django import forms

class CustomForm(forms.Form):
    ORDER = ('field1', 'field2', 'field3')
    def __init__(self, *args, **kwargs):
        super(CustomForm, self).__init__(*args, **kwargs)
        fields = OrderedDict()
        for key in self.ORDER:
            fields[key] = self.fields.pop(key)
        self.fields = fields

Upvotes: 6

Daniel Quinn
Daniel Quinn

Reputation: 6408

When we upgraded to Django 1.7 Skyjur's use of .keyOrder stopped working (Django is using collections.OrderedDict now instead). As a result, I had to find a work-around and this is what appears to be working for me:

from collections import OrderedDict
...
class MyForm(forms
    def __init__(self, *args, **kwargs):
        fields = OrderedDict()
        for key in ("my_preferred_first_field", "my_preferred_second_field"):
            fields[key] = self.fields.pop(key)
        for key, value in self.fields.items():
            fields[key] = value
        self.fields = fields

Upvotes: 2

Ski
Ski

Reputation: 14487

Re-ordering is quite tedious:

# django's SortedDict stores ordering of its fields in this list-type attribute:
keyorder = self.fields.keyOrder

# Remove fields which we want to displace:
keyorder.remove('street')
keyorder.remove('city')

# Get position where we want them to put in:
i = keyorder.index('name') + 1

# Insert items back into the list:
keyorder[i:i] = ['city', 'street']

probably better just to list all the fields again in proper order:

class MyForm(ModelForm):
    class Meta:
       model=Customer
       fields=[..., 'name', 'street', 'city', ...]

Upvotes: 7

Related Questions