表单初始化后,Django设置字段值


116

表单初始化后,我试图将字段设置为某个值。

例如,我有以下课程。

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

在视图中,我希望能够执行以下操作:

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

return HttpResponse(t.render(c))

Answers:


135

由于您没有传递POST数据,因此我假设您要尝试设置的初始值将显示在表单中。执行此操作的方法是使用initial关键字。

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

请参阅Django Form文档更多说明,。

如果您在提交表单后尝试更改值,则可以使用以下方法:

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

检查上面引用的文档以获取更多有关使用的信息 cleaned_data


2
这证实了我所知道的内容,但是ModelChoiceField当我给它一个initial值时,我仍然在提供invalid_choice :(
markwalker_ 2012年

是的,这也是我的问题。并且无法更改form.data ['Email']。
GergelyPolonkai,2015年

2
我将其更改为,form.data['Email'] = GetEmailString()并且可以正常工作
psychok7,2015年

1
我需要 CustomForm(request.POST)和.is_valid()之间进行设置,所以我既不能在构造函数中使用Initial,也不能使用cleaned_data。我尝试使用form.data,但它是不可变的(Django 1.11)。
Teekin

正确的解决这个问题,应该是:form.fields['Email'].initial = GetEmailString()form.fields['keyword'].initial给你访问甚至有实例化表单后,初始化自己的价值观
vctrd

95

如果已经初始化了表单,则可以使用该字段的initial属性。例如,

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

在带有表单集的for循环中也可以很好地工作,只需使用逻辑“ formset中的表单”,就可以设置选项和初始数据,如上所示。
radtek

5
Django 1.7 / Python 3.4有另一种方法可以做到这一点吗?这对我不起作用
杰里米(Jeremy)

1
@JeremyCraigMartinez:否...您正在尝试的表单是绑定表单(传入的GET / POST数据)吗?文档说这就是为什么仅对未绑定的表单显示初始值的原因。对于绑定表单,HTML输出将使用绑定数据。,请看这里
Markus

9
正确的方法是form.initial [“ Email”] = GetEmailString()
Elio Scordo 2016年

12

如果__init__出于某种原因要在表单的方法中进行操作,则可以操作initialdict:

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'

终于找到了解决方案。谢谢。对我有用。
Almas Dusal

8

如果您要将数据添加到所收集的一组表单数据的副本中,则类似于Nigel Cohen的方法会起作用:

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

1
我不是重写原始数据的忠实拥护者。如果绝对必须这样做,则可能应该data[form.add_prefix('Email')]考虑设置前缀的情况。
2014年

2
Django 1.7 / Python 3.4有另一种方法可以做到这一点吗?这对我不起作用
Jeremy

如果不需要保留原始格式,第三行可能会短一些:form.data = form.data.copy()
ZZY 2015年

@Josh,这是需要的一种情况:使用表单来验证输入->使用输入进行处理->完成处理->擦除/修改表单的多个字段并呈现为HTML作为响应。例如,表单中有“名称”,“电子邮件”,“内容”字段,我要保留“名称”和“电子邮件”,但要擦除“内容”。这样,如果用户要提交其他POST,则无需再次输入名称/电子邮件。当然,使用相同的名称/电子邮件作为初始值来初始化新表格是一种方法,但是我认为在某些情况下擦除旧表格更简单
ZZY 2015年

我不确定我是否完全理解。但是,如果我这样做,对我来说听起来像您应该使用modelform_factory。这样,您可以生成不包含不需要字段的Form类。拥有一个没有被渲染的字段的Form类是非常危险的,因为form对象仍然会接受非渲染字段的数据。攻击者可以利用此优势。
2015年

5

如果您已经初始化了这样的表格

form = CustomForm()

那么截至2019年1月的正确方法是使用.initial替换数据。这将替换intial表格附带的字典中的数据。如果您使用某些实例进行了初始化,例如 form = CustomForm(instance=instance)

要替换表格中的数据,您需要

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

一概而论,

form.initial['field_name'] = new_value

3

只需更改您的Form.data字段:

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

再加上另一种方式:这也可以用更现代的符号表示。它只是围绕a QueryDict是不可变的事实起作用。

>>> 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">'


-12

另一种方法是,如果您已经初始化了一个表单(有或没有数据),并且需要在显示之前添加更多数据:

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

8
这对我来说失败了。我在表单的init方法中有一行如上所述的内容,它引发“ AttributeError:此QueryDict实例是不可变的”
Jonathan Hartley

该代码仅在没有任何表单数据的情况下初始化表单时才有效。结果,不会绑定诸如request.GET或request.POST之类的不可变对象,因此您将获得一个空字典(form.data),可以对其进行更改而不会出现任何错误。仅供参考,我使用的是Django
1.6.3-平板电脑的发布时间为

如果您的“ Content-Type”标头设置为“ multipart / form-data”,则此方法有效。当您使用“ application / x-www-form-urlencoded”的内容类型时,它将失败。我不知道为什么,但是调试起来很麻烦。
teewuane
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.