Django, bir form başlatıldıktan sonra alan değerini belirledi


116

Form başlatıldıktan sonra alanı belirli bir değere ayarlamaya çalışıyorum.

Örneğin, aşağıdaki sınıfa sahibim.

class CustomForm(forms.Form):
    Email = forms.EmailField(min_length=1, max_length=200)

Görünüşe göre, bunun gibi bir şey yapabilmek istiyorum:

form = CustomForm()
form["Email"] = GetEmailString()

return HttpResponse(t.render(c))

Yanıtlar:


135

POST verilerini aktarmadığınız için, yapmaya çalıştığınız şeyin formda görüntülenecek bir başlangıç ​​değeri ayarlamak olduğunu varsayacağım. Bunu yapmanın yolu initialanahtar kelimedir.

form = CustomForm(initial={'Email': GetEmailString()})

Daha fazla açıklama için Django Form belgelerine bakın .

Form gönderildikten sonra bir değeri değiştirmeye çalışıyorsanız, aşağıdaki gibi bir şey kullanabilirsiniz:

if form.is_valid():
    form.cleaned_data['Email'] = GetEmailString()

Kullanımla ilgili daha fazla bilgi için yukarıda referans verilen belgelere bakın cleaned_data


2
Bu, bildiklerimi doğrular, ancak ModelChoiceFieldbir initialdeğer verdiğimde hala
geçersiz_seçim veriyor

Evet, bu benim de sorunum. Ve form.data ['E-posta'] 'nın değiştirilmesi mümkün değildir.
GergelyPolonkai

2
benimkini olarak değiştirdim form.data['Email'] = GetEmailString()ve işe yarıyor
psychok7

1
Bunu CustomForm (request.POST) ve .is_valid () arasında ayarlamam gerekiyor , bu yüzden yapıcıda baş harfini veya clean_data'yı kullanamıyorum. Form.data kullanmayı denedim ama değişmez (Django 1.11).
Teekin

Bu sorunun doğru çözümü olmalı: Hatta formu instanciated ettikten sonra değerlerini başlatmak için size erişim sağlarform.fields['Email'].initial = GetEmailString()form.fields['keyword'].initial
vctrd

95

Formu zaten başlattıysanız, alanın ilk özelliğini kullanabilirsiniz. Örneğin,

form = CustomForm()
form.fields["Email"].initial = GetEmailString()

Ayrıca bir formset ile bir for döngüsünde harika çalışır, sadece "for formset in form" mantığını kullanın ve yukarıda görüldüğü gibi seçimleri ve ilk verileri ayarlayabilirsiniz.
radtek

5
Bunu yapmanın farklı bir yolu Django 1.7 / Python 3.4'tür? Bu benim için çalışmıyor
Jeremy

1
@JeremyCraigMartinez: Hayır ... Denediğiniz form bağlı bir form mu (GET / POST verileriyle birlikte)? Dokümanlar, Bu nedenle ilk değerlerin yalnızca ilişkisiz formlar için görüntülendiğini söylüyor . İlişkili formlar için, HTML çıktısı ilişkili verileri kullanır. buraya
Markus

9
doğru yol form.initial ["Email"] = GetEmailString ()
Elio Scordo

12

Herhangi bir __init__nedenle formun yöntemi içinde yapmak istiyorsanız , initialdikteyi değiştirebilirsiniz:

class MyForm(forms.Form):
    my_field = forms.CharField(max_length=255)

    def __init__(self, *args, **kwargs):
        super(MyForm, self).__init__(*args, **kwargs)
        self.initial['my_field'] = 'Initial value'

Sonunda çözümü buldum. Teşekkür ederim. Benim için çalıştı.
Almas Dusal

8

Toplanan form verisi setinin bir kopyasına veri ekliyor olsaydınız Nigel Cohen'in çalışması gibi bir şey işe yarardı :

form = FormType(request.POST)
if request.method == "POST":
    formcopy = form(request.POST.copy())
    formcopy.data['Email'] = GetEmailString()

1
Ham verileri geçersiz kılmanın büyük bir hayranı değilim. Bunu kesinlikle yapmanız gerekiyorsa, muhtemelen data[form.add_prefix('Email')]bir önekin ayarlandığı durumları hesaba katmalısınız.
Josh

2
Bunu yapmanın farklı bir yolu Django 1.7 / Python 3.4'tür? Bu benim için çalışmıyor
Jeremy

Orijinal şekli korumaya gerek yoksa 3. satır biraz daha kısaltılabilir:form.data = form.data.copy()
ZZY

@Josh, ihtiyacın bir senaryosu: girdiyi doğrulamak için bir form kullanın -> girdi ile işleme -> işlem tamamlandı -> formun birkaç alanını sil / değiştir ve yanıt olarak HTML'ye dönüştür. Örneğin, bir formda "ad", "e-posta", "içerik" alanları var, "ad" ve "e-posta" yı saklamak, ancak "içeriği" silmek istiyorum. Böylece, başka bir POST göndermek istiyorlarsa, kullanıcıların yeniden ad / e-posta girmeleri gerekmez. Elbette, başlangıç ​​değeri olarak aynı ada / e-postaya sahip yeni bir formu
başlatın

Tam olarak anladığımdan emin değilim. Ancak, yaparsam, bunun yerine kullanmanız gerektiği gibi geliyor bana modelform_factory. Bu şekilde, istemediğiniz alanlara sahip olmayan bir Form sınıfı oluşturabilirsiniz. Oluşturulmamış alanlar için veri kabul etmeye devam edeceğinden, işlenmemiş alanlara sahip bir Form sınıfına sahip olmak çok tehlikelidir. Bir saldırgan bunu kendi avantajı için kullanabilir.
Josh

5

Formu böyle başlattıysanız

form = CustomForm()

Ocak 2019 itibarıyla doğru yol .initial, verileri değiştirmek için kullanmaktır . Bu intial, formla birlikte gelen diktedeki verilerin yerini alacaktır . Ayrıca, aşağıdaki gibi bazı örnekleri kullanarak başlattıysanız da çalışır. form = CustomForm(instance=instance)

Formdaki verileri değiştirmek için yapmanız gerekenler

form.initial['Email'] = GetEmailString()

Bunu genellemek,

form.initial['field_name'] = new_value

3

Form.data alanınızı değiştirmeniz yeterlidir:

class ChooseProjectForm(forms.Form):
    project = forms.ModelChoiceField(queryset=project_qs)
    my_projects = forms.BooleanField()

    def __init__(self, *args, **kwargs):
        super(ChooseProjectForm, self).__init__(*args, **kwargs)
        self.data = self.data.copy()  # IMPORTANT, self.data is immutable
        # any condition:
        if self.data.get('my_projects'):
            my_projects = self.fields['project'].queryset.filter(my=True)
            self.fields['project'].queryset = my_projects
            self.fields['project'].initial = my_projects.first().pk
            self.fields['project'].empty_label = None  # disable "-----"
            self.data.update(project=my_projects.first().pk)  # Update Form data
            self.fields['project'].widget = forms.HiddenInput()  # Hide if you want

0

Karışıma başka bir yol daha eklemek için: bu da biraz daha modern notasyonla işe yarıyor. Sadece QueryDicta'nın değişmez olduğu gerçeği etrafında çalışır .

>>> the_form.data = {**f.data.dict(), 'some_field': 47}
>>> the_form['some_field'].as_widget()
'<input type="hidden" name="some_field" value="47"
        class="field-some_field" id="id_some_field">'

0

widget'ta 'değer' attr kullanın. Misal:

username = forms.CharField(
    required=False,
    widget=forms.TextInput(attrs={'readonly': True, 'value': 'CONSTANT_VALUE'}),
)

-12

Bunu yapmanın başka bir yolu, bir formu zaten başlattıysanız (veri içeren veya içermeyen) ve görüntülemeden önce daha fazla veri eklemeniz gerekiyorsa:

form = Form(request.POST.form)
form.data['Email'] = GetEmailString()

8
Bu benim için başarısız. Formumun init yönteminde yukarıdakine benzer bir satır var ve "AttributeError: Bu QueryDict örneği değişmez"
Jonathan Hartley

Bu kod, yalnızca form herhangi bir form verisi olmadan başlatıldığında çalışır. Sonuç olarak, request.GET veya request.POST gibi değişmez bir nesne bağlı olmayacak, bu nedenle herhangi bir hata olmadan değiştirilebilecek boş bir sözlük (form.data) alacaksınız. Bilginize Django 1.6.3 kullanıyorum
potar

Bu, "Content-Type" başlığınız "multipart / form-data" olarak ayarlanmışsa çalışacaktır. "Application / x-www-form-urlencoded" içerik türünü kullandığınızda başarısız olur. Nedenini bilmiyorum ama hata ayıklamak bir zırvalıktı.
teewuane
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.