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): summary = forms.CharField() description = forms.CharField(widget=forms.TextArea) class create_form(edit_form): name = forms.CharField()
The name is immutable and should only be listed when the entity is created. I use inheritance to add consistency and DRY principles. What happens which is not erroneous, in fact totally expected, is that the name field is listed last in the view/html but I'd like the name field to be on top of summary and description. I do realize that I could easily fix it by copying summary and description into create_form and loose the inheritance but I'd like to know if this is possible.
Why? Imagine you've got 100 fields in edit_form and have to add 10 fields on the top in create_form - copying and maintaining the two forms wouldn't look so sexy then. (This is not my case, I'm just making up an example)
So, how can I override this behavior?
Apparently there's no proper way to do this without going through nasty hacks (fiddling with .field attribute). The .field attribute is a SortedDict (one of Django's internal datastructures) which doesn't provide any way to reorder key:value pairs. It does how-ever provide a way to insert items at a given index but that would move the items from the class members and into the constructor. This method would work, but make the code less readable. The only other way I see fit is to modify the framework itself which is less-than-optimal in most situations.
In short the code would become something like this:
class edit_form(forms.Form): summary = forms.CharField() description = forms.CharField(widget=forms.TextArea) class create_form(edit_form): def __init__(self,*args,**kwargs): forms.Form.__init__(self,*args,**kwargs) self.fields.insert(0,'name',forms.CharField())
That shut me up :)
Django 1.9 adds a new
field_order, allowing to order the field regardless their order of declaration in the class.
class MyForm(forms.Form): summary = forms.CharField() description = forms.CharField(widget=forms.TextArea) author = forms.CharField() notes = form.CharField() field_order = ['author', 'summary']
Missing fields in
field_order keep their order in the class and are appended after the ones specified in the list. The example above will produce the fields in this order:
['author', 'summary', 'description', 'notes']
See the documentation: https://docs.djangoproject.com/en/stable/ref/forms/api/#notes-on-field-ordering
I had this same problem and I found another technique for reordering fields in the Django CookBook:
class EditForm(forms.Form): summary = forms.CharField() description = forms.CharField(widget=forms.TextArea) class CreateForm(EditForm): name = forms.CharField() def __init__(self, *args, **kwargs): super(CreateForm, self).__init__(*args, **kwargs) self.fields.keyOrder = ['name', 'summary', 'description']
Original answer: Django 1.9 will support this by default on the form with
class MyForm(forms.Form): ... field_order = ['field_1', 'field_2'] ...