Django menetapkan nilai formulir default

241

Saya memiliki Model sebagai berikut:

class TankJournal(models.Model):
    user = models.ForeignKey(User)
    tank = models.ForeignKey(TankProfile)
    ts = models.IntegerField(max_length=15)
    title = models.CharField(max_length=50)
    body = models.TextField()

Saya juga memiliki formulir model untuk model di atas sebagai berikut:

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput()) 

    class Meta:
        model = TankJournal
        exclude = ('user','ts')

Saya ingin tahu cara mengatur nilai default untuk bidang tersembunyi tangki itu. Inilah fungsi saya untuk menunjukkan / menyimpan formulir sejauh ini:

def addJournal(request, id=0):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/')

    # checking if they own the tank
    from django.contrib.auth.models import User
    user = User.objects.get(pk=request.session['id'])

    if request.method == 'POST':
        form = JournalForm(request.POST)
        if form.is_valid():
            obj = form.save(commit=False)

            # setting the user and ts
            from time import time
            obj.ts = int(time())
            obj.user = user

            obj.tank = TankProfile.objects.get(pk=form.cleaned_data['tank_id'])

            # saving the test
            obj.save()

    else:
        form = JournalForm()

    try:
        tank = TankProfile.objects.get(user=user, id=id)
    except TankProfile.DoesNotExist:
        return HttpResponseRedirect('/error/')
Mike
sumber

Jawaban:

402

Anda dapat menggunakan inisial yang dijelaskan di sini

Anda memiliki dua opsi untuk mengisi nilai saat memanggil konstruktor formulir:

form = JournalForm(initial={'tank': 123})

atau atur nilai dalam definisi bentuk:

tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 
Sergey Golovchenko
sumber
Dan bagaimana variabel itu initialditeruskan ke bentuk aktual? Dalam model formulir yang sebenarnya, apakah kita harus menulis sebagai parameter / argumen?
mgPePe
2
@harhar Ini ajaib. ;-) (Atau lebih tepatnya, Django form constructor memahami variabel "awal" khusus dan beralih melalui isinya tanpa Anda perlu melakukan sesuatu yang ekstra). Secara pribadi, saya lebih suka menentukan nilai default dalam definisi bentuk dan hanya menggunakan mekanisme awal = ... jika default yang diinginkan adalah nilai dinamis (misalnya sesuatu yang dimasukkan oleh pengguna, atau berdasarkan login, lokasi geografis, dll.)
Richard J Foster
66
inisial tidak default. Nilai awal tidak berlaku jika formulir telah terikat :(.
clime
4
Mengomentari di sini untuk menyebutkan usecase lain di mana solusi param awal ini akan membantu: Saat mengirim tautan pendaftaran kepada seseorang jika Anda ingin mengisi ulang email / id atau kredensial lain pada formulir pendaftaran maka dalam hal ini Anda tidak dapat menulisnya di model itu sendiri sebagai dinamiknya bukan Anda perlu memanggil konstruktor dengan param awal seperti yang disebutkan oleh @ umnik700. Bagus sekali!
Keshav Agrawal
1
@ Unggl: Jangan mengganti View.get_formuntuk mengatur data awal. CBV apa pun dengan FormMixin (pada dasarnya semua CBV yang membuat atau mengedit data) dapat menggunakan initialvariabel tingkat kelas (untuk default yang tidak berubah) atau Anda dapat mengganti FormMixin.get_initial()untuk mengembalikan dikt nilai awal yang akan diteruskan ke konstruktor formulir (untuk default dinamis) .)
GDorn
29

Solusi lain: Tetapkan inisial setelah membuat formulir:

form.fields['tank'].initial = 123
Andreas Zwerger
sumber
Ini berfungsi untuk kebutuhan saya, hanya init satu bidang dalam formulir. Terima kasih.
bl4ckb1rd
11

Saya punya solusi lain ini (saya mempostingnya kalau-kalau ada orang lain karena saya menggunakan metode berikut dari model):

class onlyUserIsActiveField(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(onlyUserIsActiveField, self).__init__(*args, **kwargs)
        self.fields['is_active'].initial = False

    class Meta:
        model = User
        fields = ['is_active']
        labels = {'is_active': 'Is Active'}
        widgets = {
            'is_active': forms.CheckboxInput( attrs={
                            'class':          'form-control bootstrap-switch',
                            'data-size':      'mini',
                            'data-on-color':  'success',
                            'data-on-text':   'Active',
                            'data-off-color': 'danger',
                            'data-off-text':  'Inactive',
                            'name':           'is_active',

            })
        }

Inisial ditetapkan pada __init__fungsi sebagaiself.fields['is_active'].initial = False

Izuzvo
sumber
0

Saya harap ini dapat membantu Anda:

form.instance.updatedby = form.cleaned_data['updatedby'] = request.user.id
Kode47
sumber
0

Seperti yang dijelaskan dalam dokumen Django , initialtidak default.

  • Nilai awal suatu bidang dimaksudkan untuk ditampilkan dalam HTML. Tetapi jika pengguna menghapus nilai ini, dan akhirnya mengirim kembali nilai kosong untuk bidang ini, initialnilainya hilang. Jadi, Anda tidak mendapatkan apa yang diharapkan oleh perilaku default .

  • The standar perilaku: nilai bahwa proses validasi akan mengambil jika dataargumen tidak mengandung nilai untuk lapangan.

Untuk mengimplementasikannya, cara mudah adalah menggabungkan initialdan clean_<field>():

class JournalForm(ModelForm):
    tank = forms.IntegerField(widget=forms.HiddenInput(), initial=123) 

    (...)

    def clean_tank(self):
        if not self['tank'].html_name in self.data:
            return self.fields['tank'].initial
        return self.cleaned_data['tank']
Delesi Timothé
sumber