Jika saya memiliki bentuk Django seperti:
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField()
sender = forms.EmailField()
Dan saya memanggil metode as_table () dari turunan bentuk ini, Django akan membuat bidang sebagai urutan yang sama seperti ditentukan di atas.
Pertanyaan saya adalah bagaimana Django mengetahui urutan variabel kelas dimana didefinisikan?
(Juga bagaimana cara mengganti urutan ini, misalnya ketika saya ingin menambahkan bidang dari metode init kelas ?)
sumber
Baru di Django 1.9 adalah Form.field_order dan 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']
sumber
Saya melanjutkan dan menjawab pertanyaan saya sendiri. Inilah jawaban untuk referensi di masa mendatang:
Di Django
form.py
melakukan beberapa sihir gelap menggunakan__new__
metode untuk memuat variabel kelas Anda pada akhirnya keself.fields
dalam urutan yang ditentukan dalam kelas.self.fields
adalahSortedDict
turunan Django (didefinisikan dalamdatastructures.py
).Jadi untuk menimpa ini, katakanlah dalam contoh saya Anda ingin pengirim datang lebih dulu tetapi perlu menambahkannya dalam metode init , Anda akan melakukan:
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())))
sumber
self.fields.insert( 0, 'sender', self.fields['sender'] )
Bidang dicantumkan dalam urutan yang ditentukan dalam ModelClass._meta.fields. Namun jika Anda ingin mengubah urutan di Form, Anda bisa melakukannya dengan menggunakan fungsi keyOrder. Sebagai contoh :
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']
sumber
Dengan Django> = 1.7 Anda harus memodifikasi
ContactForm.base_fields
seperti di bawah ini:from collections import OrderedDict ... class ContactForm(forms.Form): ... ContactForm.base_fields = OrderedDict( (k, ContactForm.base_fields[k]) for k in ['your', 'field', 'in', 'order'] )
Trik ini digunakan di Django Admin
PasswordChangeForm
: Sumber di Githubsumber
PasswordChangeForm
mengubah urutan bidang, jadi contoh Anda kebetulan sangat berguna bagi saya. Sepertinya itu karenabase_fields
tidak terbawa ke subclass. Solusinya tampaknya dikatakanPasswordChangeFormSubclass.base_fields = PasswordChangeForm.base_fields
setelah definisi `PasswordChangeFormSubclassContactForm.base_fields[k]
saat membuat dict yang dipesan. Ada kesalahan ketik jawabannya, saya akan mengeditBidang formulir memiliki atribut untuk pesanan pembuatan, disebut
creation_counter
..fields
atribut adalah kamus, jadi menambahkan ke kamus dan mengubahcreation_counter
atribut di semua bidang untuk mencerminkan pengurutan baru sudah cukup (jangan pernah mencoba ini).sumber
Gunakan penghitung di kelas Lapangan. Urutkan berdasarkan penghitung itu:
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
Keluaran:
[Field('b'), Field('a'), Field('c')]
sumber
Dari bentuk Django 1.7 gunakan OrderedDict yang tidak mendukung operator tambahan. Jadi, Anda harus membangun kembali kamus dari awal ...
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
sumber
Untuk referensi di masa mendatang: banyak hal telah berubah sedikit sejak bentuk baru. Ini adalah salah satu cara menyusun ulang bidang dari kelas formulir dasar yang tidak dapat Anda kendalikan:
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
Juga, ada sedikit dokumentasi tentang SortedDict yang
base_fields
digunakan di sini: http://code.djangoproject.com/wiki/SortedDictsumber
Jika salah satu
fields = '__all__'
:class AuthorForm(ModelForm): class Meta: model = Author fields = '__all__'
atau
exclude
digunakan:class PartialAuthorForm(ModelForm): class Meta: model = Author exclude = ['title']
Kemudian Django mereferensikan urutan bidang seperti yang ditentukan dalam model . Ini baru saja menarik perhatian saya, jadi saya pikir saya akan menyebutkannya. Ini direferensikan di dokumen ModelForm :
sumber
Cara termudah untuk memesan bidang dalam formulir django 1.9 adalah dengan menggunakan
field_order
formulir Anda Form.field_orderIni contoh kecilnya
class ContactForm(forms.Form): subject = forms.CharField(max_length=100) message = forms.CharField() sender = forms.EmailField() field_order = ['sender','message','subject']
Ini akan menampilkan semuanya dalam urutan yang Anda tentukan di
field_order
dict.sumber
Menggunakan
fields
diMeta
kelas dalam adalah hal yang berhasil bagi sayaDjango==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']
Sesimpel itu.
sumber
django.forms
tidak berfungsiSaya telah menggunakan ini untuk memindahkan bidang tentang:
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)
Ini berfungsi di 1.5 dan saya cukup yakin ini masih berfungsi di versi yang lebih baru.
sumber
Ini ada hubungannya dengan kelas meta yang digunakan dalam mendefinisikan kelas formulir. Saya pikir itu menyimpan daftar internal bidang dan jika Anda memasukkan ke tengah daftar itu mungkin berhasil. Sudah lama sejak saya melihat kode itu.
sumber