40π
I went ahead and answered my own question. Hereβs the answer for future reference:
In Django form.py
does some dark magic using the __new__
method to load your class variables ultimately into self.fields
in the order defined in the class. self.fields
is a Django SortedDict
instance (defined in datastructures.py
).
So to override this, say in my example you wanted sender to come first but needed to add it in an init method, you would do:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
def __init__(self,*args,**kwargs):
forms.Form.__init__(self,*args,**kwargs)
#first argument, index is the position of the field you want it to come before
self.fields.insert(0,'sender',forms.EmailField(initial=str(time.time())))
102π
New to Django 1.9 is Form.field_order and Form.order_fields().
# forms.Form example
class SignupForm(forms.Form):
password = ...
email = ...
username = ...
field_order = ['username', 'email', 'password']
# forms.ModelForm example
class UserAccount(forms.ModelForm):
custom_field = models.CharField(max_length=254)
def Meta:
model = User
fields = ('username', 'email')
field_order = ['username', 'custom_field', 'password']
- [Django]-How can I temporarily disable a foreign key constraint in MySQL?
- [Django]-Manager isn't accessible via model instances
- [Django]-Django model CharField: max_length does not work?
90π
[NOTE: this answer is now pretty completely outdated β please see the discussion below it, and more recent answers].
If f
is a form, its fields are f.fields
, which is a django.utils.datastructures.SortedDict
(it presents the items in the order they are added). After form construction f.fields has a keyOrder attribute, which is a list containing the field names in the order they should be presented. You can set this to the correct ordering (though you need to exercise care to ensure you donβt omit items or add extras).
Hereβs an example I just created in my current project:
class PrivEdit(ModelForm):
def __init__(self, *args, **kw):
super(ModelForm, self).__init__(*args, **kw)
self.fields.keyOrder = [
'super_user',
'all_districts',
'multi_district',
'all_schools',
'manage_users',
'direct_login',
'student_detail',
'license']
class Meta:
model = Privilege
- [Django]-What is the difference between cached_property in Django vs. Python's functools?
- [Django]-Django β "no module named django.core.management"
- [Django]-CSV new-line character seen in unquoted field error
11π
Fields are listed in the order they are defined in ModelClass._meta.fields. But if you want to change order in Form, you can do by using keyOrder function.
For example :
class ContestForm(ModelForm):
class Meta:
model = Contest
exclude=('create_date', 'company')
def __init__(self, *args, **kwargs):
super(ContestForm, self).__init__(*args, **kwargs)
self.fields.keyOrder = [
'name',
'description',
'image',
'video_link',
'category']
- [Django]-Programmatically saving image to Django ImageField
- [Django]-Unittest Django: Mock external API, what is proper way?
- [Django]-How to drop all tables from the database with manage.py CLI in Django?
6π
With Django >= 1.7 your must modify ContactForm.base_fields
as below:
from collections import OrderedDict
...
class ContactForm(forms.Form):
...
ContactForm.base_fields = OrderedDict(
(k, ContactForm.base_fields[k])
for k in ['your', 'field', 'in', 'order']
)
This trick is used in Django Admin PasswordChangeForm
: Source on Github
- [Django]-Macros in django templates
- [Django]-Logging in Django and gunicorn
- [Django]-How do I use django rest framework to send a file in response?
5π
Form fields have an attribute for creation order, called creation_counter
. .fields
attribute is a dictionary, so simple adding to dictionary and changing creation_counter
attributes in all fields to reflect new ordering should suffice (never tried this, though).
- [Django]-Django rest framework, use different serializers in the same ModelViewSet
- [Django]-How to get value from form field in django framework?
- [Django]-Django Generic Views using decorator login_required
5π
Use a counter in the Field class. Sort by that counter:
import operator
import itertools
class Field(object):
_counter = itertools.count()
def __init__(self):
self.count = Field._counter.next()
self.name = ''
def __repr__(self):
return "Field(%r)" % self.name
class MyForm(object):
b = Field()
a = Field()
c = Field()
def __init__(self):
self.fields = []
for field_name in dir(self):
field = getattr(self, field_name)
if isinstance(field, Field):
field.name = field_name
self.fields.append(field)
self.fields.sort(key=operator.attrgetter('count'))
m = MyForm()
print m.fields # in defined order
Output:
[Field('b'), Field('a'), Field('c')]
- [Django]-Django switching, for a block of code, switch the language so translations are done in one language
- [Django]-How to 'bulk update' with Django?
- [Django]-How to monkey patch Django?
4π
If either fields = '__all__'
:
class AuthorForm(ModelForm):
class Meta:
model = Author
fields = '__all__'
or exclude
are used:
class PartialAuthorForm(ModelForm):
class Meta:
model = Author
exclude = ['title']
Then Django references the order of fields as defined in the model. This just caught me out, so I thought Iβd mention it. Itβs referenced in the ModelForm docs:
If either of these are used, the order the fields appear in the form will be the order the fields are defined in the model, with ManyToManyField instances appearing last.
- [Django]-Problems with contenttypes when loading a fixture in Django
- [Django]-How to change site title, site header and index title in Django Admin?
- [Django]-Django switching, for a block of code, switch the language so translations are done in one language
4π
As of Django 1.7 forms use OrderedDict which does not support the append operator. So you have to rebuild the dictionary from scratchβ¦
class ChecklistForm(forms.ModelForm):
class Meta:
model = Checklist
fields = ['name', 'email', 'website']
def __init__(self, guide, *args, **kwargs):
self.guide = guide
super(ChecklistForm, self).__init__(*args, **kwargs)
new_fields = OrderedDict()
for tier, tasks in guide.tiers().items():
questions = [(t['task'], t['question']) for t in tasks if 'question' in t]
new_fields[tier.lower()] = forms.MultipleChoiceField(
label=tier,
widget=forms.CheckboxSelectMultiple(),
choices=questions,
help_text='desired set of site features'
)
new_fields['name'] = self.fields['name']
new_fields['email'] = self.fields['email']
new_fields['website'] = self.fields['website']
self.fields = new_fields
- [Django]-How to expire session due to inactivity in Django?
- [Django]-">", "<", ">=" and "<=" don't work with "filter()" in Django
- [Django]-Django :How to integrate Django Rest framework in an existing application?
3π
For future reference: things have changed a bit since newforms. This is one way of reordering fields from base formclasses you have no control over:
def move_field_before(form, field, before_field):
content = form.base_fields[field]
del(form.base_fields[field])
insert_at = list(form.base_fields).index(before_field)
form.base_fields.insert(insert_at, field, content)
return form
Also, thereβs a little bit of documentation about the SortedDict that base_fields
uses here: http://code.djangoproject.com/wiki/SortedDict
- [Django]-Laravel's dd() equivalent in django
- [Django]-How to use subquery in django?
- [Django]-Foreign key from one app into another in Django
2π
The easiest way to order fields in django 1.9 forms is to use field_order
in your form Form.field_order
Here is a small example
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
field_order = ['sender','message','subject']
This will show everything in the order you specified in field_order
dict.
- [Django]-Django Form File Field disappears on form error
- [Django]-Django development server reload takes too long
- [Django]-Alowing 'fuzzy' translations in django pages?
2π
To add something, you can use this (Django 3+):
class ...(forms.ModelForm):
field = ...
class Meta:
model = Xxxxxx
fields = '__all__'
field_order = ['field', '__all__']
__all__
works
- [Django]-Data Mining in a Django/Postgres application
- [Django]-Django filter queryset __in for *every* item in list
- [Django]-Django: Open uploaded file while still in memory; In the Form Clean method?
1π
Using fields
in inner Meta
class is what worked for me on Django==1.6.5
:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Example form declaration with custom field order.
"""
from django import forms
from app.models import AppModel
class ExampleModelForm(forms.ModelForm):
"""
An example model form for ``AppModel``.
"""
field1 = forms.CharField()
field2 = forms.CharField()
class Meta:
model = AppModel
fields = ['field2', 'field1']
As simple as that.
- [Django]-How to force Django models to be released from memory
- [Django]-Django development server reload takes too long
- [Django]-Storing an Integer Array in a Django Database
1π
Iβve used this to move fields about:
def move_field_before(frm, field_name, before_name):
fld = frm.fields.pop(field_name)
pos = frm.fields.keys().index(before_name)
frm.fields.insert(pos, field_name, fld)
This works in 1.5 and Iβm reasonably sure it still works in more recent versions.
- [Django]-How to set environment variables in PyCharm?
- [Django]-Django 1.8 KeyError: 'manager' on relationship
- [Django]-How to do math in a Django template?
1π
None of these answers worked for me, Actually, you do not have to do anything custom, you can just order the fields in the order you want in your Model class. For eg β¦ the below code
from django.db import models
class Student(models.Model):
class Meta:
verbose_name_plural = "categories"
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=300)
nick_name = models.CharField(max_length=300)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
Your admin interface for model Will display the fields exactly in the same order in which you have declared in this case it will be (id, name, nick_name )
- [Django]-Remove pk field from django serialized objects
- [Django]-Django β how to visualize signals and save overrides?
- [Django]-How do I match the question mark character in a Django URL?
0π
It has to do with the meta class that is used in defining the form class. I think it keeps an internal list of the fields and if you insert into the middle of the list it might work. It has been a while since I looked at that code.
- [Django]-Add custom form fields that are not part of the model (Django)
- [Django]-Difference between User.objects.create_user() vs User.objects.create() vs User().save() in django
- [Django]-Disabled field is not passed through β workaround needed
0π
The order of the fields in the form depends on the order of the enumeration in the View , tested in Django 4.0.5.
class Sec_CreateView(CreateView):
model = Sec
template_name = 'forms/sec_create.html'
fields = ['rto', 'ssid', 'lic', 'IPv4', 'vlans']
- [Django]-Cannot set Django to work with smtp.gmail.com
- [Django]-Choose test database?
- [Django]-Chaining multiple filter() in Django, is this a bug?