Ini diperbaiki di Django 1.9 dengan form_kwargs .
Saya memiliki Formulir Django yang terlihat seperti ini:
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(queryset=ServiceOption.objects.none())
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1, widget=custom_widgets.SmallField())
def __init__(self, *args, **kwargs):
affiliate = kwargs.pop('affiliate')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["option"].queryset = ServiceOption.objects.filter(affiliate=affiliate)
Saya menyebut formulir ini dengan sesuatu seperti ini:
form = ServiceForm(affiliate=request.affiliate)
Di mana request.affiliate
pengguna yang masuk Ini berfungsi sebagaimana dimaksud.
Masalah saya adalah saya sekarang ingin mengubah bentuk tunggal ini menjadi sebuah formset. Apa yang saya tidak tahu adalah bagaimana saya bisa meneruskan informasi afiliasi ke formulir individu ketika membuat formset. Menurut dokumen untuk membuat format dari ini saya perlu melakukan sesuatu seperti ini:
ServiceFormSet = forms.formsets.formset_factory(ServiceForm, extra=3)
Dan kemudian saya harus membuatnya seperti ini:
formset = ServiceFormSet()
Sekarang bagaimana saya bisa meneruskan afiliasi = request.affiliate ke formulir individual dengan cara ini?
sumber
functools.partial
bukan Djangodjango.utils.functional.curry
. Mereka melakukan hal yang sama, kecuali yangfunctools.partial
mengembalikan tipe callable yang berbeda dan bukan fungsi Python biasa, danpartial
tipe tersebut tidak mengikat sebagai metode instance, yang dengan rapi memecahkan masalah thread komentar ini sebagian besar dikhususkan untuk debugging.Cara Dokumen Resmi
Django 2.0:
https://docs.djangoproject.com/en/2.0/topics/forms/formsets/#passing-custom-parameters-to-formset-forms
sumber
Saya akan membangun kelas bentuk secara dinamis dalam suatu fungsi, sehingga memiliki akses ke afiliasi melalui penutupan:
Sebagai bonus, Anda tidak perlu menulis ulang kueryset di bidang opsi. The downside adalah bahwa subclassing sedikit funky. (Setiap subkelas harus dibuat dengan cara yang sama.)
edit:
Menanggapi komentar, Anda dapat memanggil fungsi ini tentang tempat yang akan Anda gunakan nama kelas:
sumber
Inilah yang berhasil bagi saya, Django 1.7:
Semoga ini bisa membantu seseorang, butuh waktu lama bagi saya untuk mengetahuinya;)
sumber
staticmethod
diperlukan di sini?Saya suka solusi penutupan untuk menjadi "lebih bersih" dan lebih Pythonic (jadi +1 ke jawaban mmarshall) tetapi formulir Django juga memiliki mekanisme panggilan balik yang dapat Anda gunakan untuk memfilter queryset dalam format.
Ini juga tidak didokumentasikan, yang saya pikir merupakan indikator yang mungkin tidak disukai oleh para Django.
Jadi pada dasarnya Anda membuat formset Anda sama tetapi menambahkan callback:
Ini membuat instance kelas yang terlihat seperti ini:
Ini seharusnya memberi Anda ide umum. Ini sedikit lebih kompleks membuat callback menjadi metode objek seperti ini, tetapi memberi Anda sedikit lebih banyak fleksibilitas daripada melakukan fungsi callback sederhana.
sumber
Saya ingin menempatkan ini sebagai komentar untuk jawaban Carl Meyers, tetapi karena itu memerlukan poin saya hanya menempatkannya di sini. Ini membutuhkan waktu 2 jam untuk mencari tahu jadi saya harap ini akan membantu seseorang.
Catatan tentang penggunaan inlineformset_factory.
Saya menggunakan solusi itu sendiri dan bekerja dengan sempurna, sampai saya mencobanya dengan inlineformset_factory. Saya menjalankan Django 1.0.2 dan mendapatkan beberapa pengecualian KeyError yang aneh. Saya memutakhirkan ke bagasi terbaru dan langsung bekerja.
Sekarang saya dapat menggunakannya mirip dengan ini:
sumber
modelformset_factory
. Terima kasih atas jawaban ini!Pada komit e091c18f50266097f648efc7cac2503968e9d217 pada Selasa 14 Agustus 23:44:46 2012 +200 solusi yang diterima tidak dapat bekerja lagi.
Versi saat ini dari fungsi django.forms.models.modelform_factory () menggunakan "teknik konstruksi tipe", memanggil fungsi type () pada formulir yang dilewati untuk mendapatkan tipe metaclass, kemudian menggunakan hasilnya untuk membangun objek kelas dari objeknya. ketik dengan cepat ::
Ini berarti bahkan
curry
ed ataupartial
objek yang dilewatkan sebagai ganti bentuk "menyebabkan bebek menggigit Anda" sehingga berbicara: itu akan memanggil fungsi dengan parameter konstruksiModelFormClass
objek, mengembalikan pesan kesalahan ::Untuk mengatasi ini, saya menulis fungsi generator yang menggunakan penutupan untuk mengembalikan subkelas dari kelas yang ditentukan sebagai parameter pertama, yang kemudian memanggil
super.__init__
setelahupdate
kwarg dengan yang disediakan pada panggilan fungsi generator ::Kemudian dalam kode Anda, Anda akan memanggil form factory sebagai ::
peringatan:
sumber
Solusi Carl Meyer terlihat sangat elegan. Saya mencoba menerapkannya untuk modelformsets. Saya mendapat kesan bahwa saya tidak bisa memanggil metode statis dalam suatu kelas, tetapi hal berikut ini bisa dijelaskan:
Dalam pandangan saya, jika saya melakukan sesuatu seperti ini:
Kemudian kata kunci "permintaan" akan disebarkan ke semua bentuk anggota dari rangkaian saya. Saya senang, tetapi saya tidak tahu mengapa ini bekerja - sepertinya salah. Ada saran?
sumber
MyFormSet.form.Meta.model
.MyFormSet.form().Meta.model
. Jelas sekali.Saya menghabiskan beberapa waktu untuk mencari tahu masalah ini sebelum saya melihat posting ini.
Solusi yang saya temukan adalah solusi penutupan (dan ini adalah solusi yang pernah saya gunakan sebelumnya dengan bentuk model Django).
Saya mencoba metode curry () seperti yang dijelaskan di atas, tetapi saya tidak bisa membuatnya bekerja dengan Django 1.0 jadi pada akhirnya saya kembali ke metode penutupan.
Metode penutupan sangat rapi dan hanya sedikit keanehan adalah bahwa definisi kelas bersarang di dalam tampilan atau fungsi lain. Saya pikir fakta bahwa ini terlihat aneh bagi saya adalah hangup dari pengalaman pemrograman saya sebelumnya dan saya pikir seseorang dengan latar belakang dalam bahasa yang lebih dinamis tidak akan kelopak mata!
sumber
Saya harus melakukan hal serupa. Ini mirip dengan
curry
solusinya:sumber
berdasarkan jawaban ini saya menemukan solusi yang lebih jelas:
Dan jalankan dalam tampilan seperti
sumber
Saya seorang pemula di sini jadi saya tidak bisa menambahkan komentar. Saya harap kode ini juga berfungsi:
seperti untuk menambahkan parameter tambahan ke formset,
BaseFormSet
bukan form.sumber