Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 272
pdxMobile Avatar asked Feb 22 '11 02:02

pdxMobile


4 Answers

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.

like image 66
Algor Avatar answered Nov 17 '22 22:11

Algor


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', ...]
like image 7
Ski Avatar answered Nov 17 '22 23:11

Ski


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
like image 6
brucegarro Avatar answered Nov 17 '22 23:11

brucegarro


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
like image 2
Daniel Quinn Avatar answered Nov 17 '22 22:11

Daniel Quinn