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?

Rory
sumber

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.

christophe31
sumber
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 }}

semente
sumber
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.

Shay Rybak
sumber
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.

ya
sumber
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()
anjaneyulubatta505
sumber
1

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

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

Anda bisa menggunakan css:

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

Ini akan membuat bidang dan labelnya tidak terlihat.

pengguna20310
sumber