Ubah bidang formulir Django ke bidang tersembunyi


128

Saya memiliki formulir Django dengan a RegexField , yang sangat mirip dengan bidang input teks normal.

Dalam pandangan saya, dalam kondisi tertentu saya ingin menyembunyikannya dari pengguna, dan mencoba untuk menjaga bentuknya senada mungkin. Apa cara terbaik untuk mengubah bidang ini menjadi HiddenInputbidang?

Saya tahu saya bisa mengatur atribut di lapangan dengan:

form['fieldname'].field.widget.attr['readonly'] = 'readonly'

Dan saya dapat mengatur nilai awal yang diinginkan dengan:

form.initial['fieldname'] = 'mydesiredvalue'

Namun, itu tidak akan mengubah bentuk widget.

Apa cara terbaik / paling "django-y" / paling tidak "hacky" untuk menjadikan bidang ini <input type="hidden">bidang?

Jawaban:


169

Jika Anda memiliki templat dan tampilan khusus, Anda dapat mengecualikan bidang dan gunakan {{ modelform.instance.field }}untuk mendapatkan nilai.

Anda juga dapat memilih untuk menggunakan tampilan:

form.fields['field_name'].widget = forms.HiddenInput()

tapi saya tidak yakin itu akan melindungi metode simpan pada posting.

Semoga ini bisa membantu.


1
Saya berakhir dengan &quot;&quot; is not a valid value for a primary key.metode is_valid setelah menggunakan solusi ini.
Jens Timmerman

Kedengarannya aneh. Saya pikir itu terkait dengan sesuatu yang lain, apakah Anda menampilkan sebagai HiddenInput kunci utama dari objek yang Anda buat? Jika ya, sebaiknya tidak.
christophe31

Mungkin ini tidak perlu dikatakan, tetapi Anda harus mengimpor formulir sebelum ini berfungsi. from django import forms
Teewuane

2
pada 1,7 gunakan sintaks ini: di hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput())mana kuncinya adalah sintaks widget yang lebih baru di akhir. Tweak untuk kebutuhan Anda.
Marc

196

Ini mungkin juga berguna: {{ form.field.as_hidden }}


3
Ini adalah jawaban IMHO terbaik. Saya selalu benci menggunakan kode Python "controller" untuk menentukan tampilan bidang formulir.
trpt4him

Saya sering membuat Templat formulir umum dengan crispyforms. Jika Anda menggunakan crispyforms atau menampilkan bidang dalam forloop sederhana karena Anda menginginkan struktur formulir di kelas formulir, widget yang menimpa dalam formulir adalah cara yang baik untuk melakukannya. Namun jika Anda mengelola rendering formulir Anda ke dalam template Anda, memang, solusi ini jauh lebih jelas / bersih.
christophe31

Perlu dicatat bahwa ini tampaknya menghapus semua kelas yang telah Anda lamar ke bidang sebelumnya ...
John Aaron

59

opsi yang berfungsi untuk saya, tentukan bidang dalam bentuk asli sebagai:

forms.CharField(widget = forms.HiddenInput(), required = False)

maka ketika Anda menimpanya di Kelas baru itu akan menjaga tempatnya.


45

Pertama, jika Anda tidak ingin pengguna mengubah data, maka tampak lebih bersih untuk mengecualikan bidang tersebut. Memasukkannya sebagai bidang tersembunyi hanya menambahkan lebih banyak data untuk dikirim melalui kabel dan mengundang pengguna jahat untuk memodifikasinya saat Anda tidak menginginkannya. Jika Anda memiliki alasan yang baik untuk memasukkan bidang tetapi menyembunyikannya, Anda bisa meneruskan argumen kata kunci ke konstruktor modelform. Sesuatu seperti ini mungkin:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
    def __init__(self, *args, **kwargs):
        from django.forms.widgets import HiddenInput
        hide_condition = kwargs.pop('hide_condition',None)
        super(MyModelForm, self).__init__(*args, **kwargs)
        if hide_condition:
            self.fields['fieldname'].widget = HiddenInput()
            # or alternately:  del self.fields['fieldname']  to remove it from the form altogether.

Lalu menurut Anda:

form = MyModelForm(hide_condition=True)

Saya lebih suka pendekatan ini untuk memodifikasi internal modelform dalam tampilan, tapi ini masalah selera.


11
cukup tip sederhana, kwargs.pop ('hide_condition', False) alih-alih kwargs ['hide_condition']. Anda akan menangani kasus no arg, memiliki default dan del dalam waktu yang bersamaan.
christophe31

2
terima kasih atas tipnya, christophe31. Saya telah memperbarui dengan saran Anda, karena membuat kode lebih jelas.
rych

1
Apakah mungkin menyembunyikan bidang dengan pendekatan ini sepenuhnya? Seperti jika Anda mengaktifkan class Meta: exclude = ["fieldname"]. Masalahnya di sini adalah, bahwa pendekatan Meta "statis", tapi saya butuh sesuatu yang dinamis. Lihat stackoverflow.com/questions/20243735/…
Themerius

You cab di def __init __ (self, hide_condition = Benar, * args, ** kwargs) yang merupakan cara terbersih ...
Visgean Skeloru

22

Untuk bentuk normal bisa Anda lakukan

class MyModelForm(forms.ModelForm):
    slug = forms.CharField(widget=forms.HiddenInput())

Jika Anda memiliki formulir model, Anda dapat melakukan hal berikut

class MyModelForm(forms.ModelForm):
    class Meta:
        model = TagStatus
        fields = ('slug', 'ext')
        widgets = {'slug': forms.HiddenInput()}

Anda juga dapat mengganti __init__metode

class Myform(forms.Form):
    def __init__(self, *args, **kwargs):
        super(Myform, self).__init__(*args, **kwargs)
        self.fields['slug'].widget = forms.HiddenInput()

1

Jika Anda ingin bidang selalu disembunyikan, gunakan yang berikut ini:

class MyForm(forms.Form):
    hidden_input = forms.CharField(widget=forms.HiddenInput(), initial="value")

0

Anda bisa menggunakan css:

#id_fieldname, label[for="id_fieldname"] {
  position: absolute;
  display: none
}

Ini akan membuat bidang dan labelnya tidak terlihat.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.