Reputation: 2078
I am trying to set the fieldorder of my form. but somehow it just stays in alphabetical order. Anyone has some suggestions? i tried class Meta: fields = ["field", "field"] and adding a keyOrder in the init
form:
class HangarFilterForm(forms.Form):
FIELDS = [
("", ""),
("warp", "Warp"),
("cargo_space", "Cargo Space"),
("smuggle_bay", "Smuggle Bay"),
("dock", "Dock/Undock"),
("enter_warp", "Enter Warp"),
("fuel_bay", "Fuel Bay"),
("fuel_cost", "Fuel Cost"),
]
PER_PAGE = [
(10, ""),
(5, "5 ships"),
(10, "10 ships"),
(25, "25 ships"),
(50, "50 ships"),
]
field_1 = forms.ChoiceField(choices=FIELDS, label="1st attribute", required=False)
field_2 = forms.ChoiceField(choices=FIELDS, label="2nd attribute", required=False)
per_page = forms.ChoiceField(choices=PER_PAGE, required=False)
def __init__(self, *args, **kwargs):
super(HangarFilterForm, self).__init__(*args, **kwargs)
self.fields['planet'] = forms.ChoiceField(
choices=[("", "")] + [ (o.id, o.name) for o in lanet.objects.all().order_by("name")],
required=False)
self.fields['type'] = forms.ChoiceField(
choices=[("", "")] + [ (o[0], o[1]) for o in ShipTemplate.SHIP_TYPES], required=False)
self.fields.keyOrder = ["planet", "type", "field_1", "field_2", "per_page"]
Upvotes: 8
Views: 7728
Reputation: 71
I used the bspink's way with some improvements. You don't need to define the fields that you don't want to change their ordering. Define only what you want to put to the top as ordered in themself.
(Be sure you are using the Python 3.7+)
class SomeForm(forms.Form):
# define only you want to put top, no need to define all of them
# unless you need more specific ordering
ordered_field_names = ['planet', 'type']
def __init__(self, *args, **kwargs):
super(SomeForm, self).__init__(*args, **kwargs)
# call initialization code
self.rearrange_field_order()
def rearrange_field_order(self):
# add defined fields first
new_fields = {field_name: self.fields.get(field_name) for field_name in self.ordered_field_names}
# then add others whose not defined in order list
for key, value in self.fields.items():
if key not in new_fields:
new_fields[key] = value
self.fields = new_fields
Upvotes: 0
Reputation: 15643
I tried setting fields
in Meta
part of form in django 2.1 and it also did the trick:
class MyForm(forms.ModelForm):
...
class Meta:
model = Contact
fields = ('field_1', 'field_2', 'field_3', 'field_4',)
Upvotes: 3
Reputation: 1335
In Django 1.9, new way of forcing the order of form's fields has been added : field_order
.
Take a look (link to version 1.9): https://docs.djangoproject.com/en/1.9/ref/forms/api/#django.forms.Form.field_order
(and a link to dev version): https://docs.djangoproject.com/en/dev/ref/forms/api/#django.forms.Form.field_order
Find below a short example (using Django 1.9)
models.py:
from django.db import models
class Project(models.Model):
end_date = models.DateField(verbose_name='End date',
blank=True)
start_date = models.DateField(verbose_name='Start date',
blank=True)
title = models.CharField(max_length=255,
blank=False,
verbose_name='Title')
def __str__(self):
return self.title
forms.py
from django.forms import ModelForm, DateTimeField, SelectDateWidget
from XXX.models import Project
class ProjectForm(ModelForm):
class Meta:
model = Project
fields = '__all__'
start_date = DateTimeField(widget=SelectDateWidget)
end_date = DateTimeField(widget=SelectDateWidget)
field_order = ['start_date', 'end_date']
In this example the fields will be rearranged to:
Upvotes: 12
Reputation: 367
Might be a little bit off topic. Using django crispy forms and their Layout objects can help a great deal with formatting forms the way you exactly want. Which includes rearranging the field order.
A sample to illustrate:
class UpdateUserForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.layout = Layout(
Field('email'),
Field('quote'),
Field('website', placeholder="http://"),
Field('logo', template="user/logoInput.html"),
HTML('<label class="control-label">Other settings</label>'),
Field('emailVisible'),
Field('subscribeToEmails'),
Field('mpEmailNotif'),
Field('showSmileys'),
Field('fullscreen'),
)
class Meta:
model = ForumUser
fields = ('email', 'emailVisible', 'subscribeToEmails', 'mpEmailNotif',
'logo', 'quote', 'website', 'showSmileys', 'fullscreen')
Upvotes: 1
Reputation: 333
This is some code that I've done in the past to rearrange the field order in forms that has worked; you could probably put this into a mixin for use elsewhere. Let me know how it goes.
from django.utils.datastructures import SortedDict
class HangarFilterForm(forms.Form):
ordered_field_names = ['planet', 'type', 'field_1', 'field_2', 'per_page']
def __init__(self, *args, **kwargs):
super(HangarFilterForm, self).__init__(*args, **kwargs)
# Your field initialisation code
self.rearrange_field_order()
def rearrange_field_order(self):
original_fields = self.fields
new_fields = SortedDict()
for field_name in self.ordered_field_names:
field = original_fields.get(field_name)
if field:
new_fields[field_name] = field
self.fields = new_fields
If you want to keep track of the original file order for some reason, you can just change original_fields
to self.original_fields
in rearrange_field_order
.
Upvotes: 2