Gre*_*reg 84 python django django-forms
如果我有一个Django表格,例如:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
Run Code Online (Sandbox Code Playgroud)
我调用此表单实例的as_table()方法,Django将按照上面指定的顺序呈现字段.
我的问题是Django如何知道定义类变量的顺序?
(另外我如何覆盖这个顺序,例如当我想从classe的init方法中添加一个字段?)
hol*_*web 89
[注意:这个答案现在已经过时了 - 请参阅下面的讨论,以及最近的答案].
如果f是一种形式,它的领域是f.fields,这是一个django.utils.datastructures.SortedDict (它呈现它们被添加的顺序选择项目).在表单构造之后,f.fields有一个keyOrder属性,该属性是一个包含字段名称的列表,按顺序显示它们.您可以将其设置为正确的顺序(尽管您需要注意确保不要省略项目或添加额外内容).
这是我刚才在当前项目中创建的一个示例:
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
Run Code Online (Sandbox Code Playgroud)
Ste*_*joa 55
Django 1.9的新功能是Form.field_order和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']
Run Code Online (Sandbox Code Playgroud)
Gre*_*reg 38
我继续前进并回答了我自己的问题.以下是未来参考的答案:
在Django form.py中,使用该__new__方法将类变量最终加载到类self.fields中定义的顺序中. self.fields是一个Django SortedDict实例(在中定义datastructures.py).
所以要覆盖它,比如在我的例子中你希望发送者先来但需要在init方法中添加它,你会这样做:
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())))
Run Code Online (Sandbox Code Playgroud)
小智 11
字段按ModelClass._meta.fields中定义的顺序列出.但是如果要在Form中更改顺序,可以使用keyOrder函数.例如 :
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']
Run Code Online (Sandbox Code Playgroud)
使用Django> = 1.7,您必须修改ContactForm.base_fields如下:
from collections import OrderedDict
...
class ContactForm(forms.Form):
...
ContactForm.base_fields = OrderedDict(
(k, ContactForm.base_fields[k])
for k in ['your', 'field', 'in', 'order']
)
Run Code Online (Sandbox Code Playgroud)
这个技巧用于Github上的 Django Admin PasswordChangeForm:Source
表单字段具有创建顺序的属性,称为creation_counter..fields属性是一个字典,所以简单地添加到字典和更改creation_counter所有字段中的属性以反映新的排序应该足够了(尽管从未尝试过这个).
在Field类中使用计数器.按该计数器排序:
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
Run Code Online (Sandbox Code Playgroud)
输出:
[Field('b'), Field('a'), Field('c')]
Run Code Online (Sandbox Code Playgroud)