在__init__方法中设置Django表单字段的初始值

45

Django 1.6

下面是一个 Django 表单类中的工作代码块。我正在构建表单字段列表所需的数据集中,可以包括任何字段的初始值,但是在表单中设置初始值时遇到了困难。下面的 if field_value: 块确实填充了初始表单字典属性,但是初始值没有显示。请注意(以防您想知道),.initial 属性直到 super() 调用后才存在。这能行吗?如果可以,那我做错了什么?谢谢!

def __init__(self, *args, **kwargs):
    id = kwargs.pop('values_id', 0)
    super(LaunchForm, self).__init__(*args, **kwargs)
    # Lotsa code here that uses the id value
    # to execute a query and build the form
    # fields and their attributes from the 
    # result set

    if field_value:
        self.initial[field_name] = field_value

1
我的问题是在设置self.initial之后才调用super.init...天哪! - MagicLAMP
6个回答

42
我也碰到了同样的问题,我通过这个方法解决了它:
def __init__(self, *args, **kwargs):
    instance = kwargs.get('instance', None)

    kwargs.update(initial={
        # 'field': 'value'
        'km_partida': '1020'
    })

    super(ViagemForm, self).__init__(*args, **kwargs)

    # all other stuff

24

尝试这种方式:

super(ViagemForm, self).__init__(*args, **kwargs)

if field_value:
    #self.initial[field_name] = field_value
    self.fields[field_name].initial = field_value

2
@ndpu - 谢谢,但这也不起作用 - 字段对象存在,并且它具有数据属性“initial”,该属性确实设置为初始值,但它没有显示在表单上。@karthikr - 建立表单字段的代码是在super()调用之后执行的,只有在执行此代码之后,我才知道初始值应该是什么。我还尝试了`self.initial.update({field_name: field_value})',但这也会使页面上的字段为空白。我还尝试将初始字段参数设置为字段定义的一部分 - 但该方法也没有成功。 - Steve Sawyer
2
好的。我使用与答案中展示的完全相同的代码,它对我有效。 - karthikr
@karthikr - 我猜你的代码能够工作是因为你在设置属性之后才调用了super()。在上周五,我对此进行了更深入的探究,发现不仅可以验证初始值是否存在,而且它还是一个必填字段,其存在会导致表单在视图的post()方法中通过is_valid()。所以,我遇到了最糟糕的情况——该值已经存在并且已经验证,但是无法在表单上显示! - Steve Sawyer
我离按照我的需求让它正常工作还有一段距离,但我正在做出一些发现,而失败可能不在于我如何填充初始值,而在于字段类型的行为(或者是我对其行为的理解)。我将发布一个新主题来探讨这个问题的方面。感谢您所有的建议。 - Steve Sawyer
你需要首先使用super初始化表单,以便使self.fields可用。 - biodiv
我先执行了 super,然后进行了更改,但它将选择字段的值设置为第一个可用的选项。对我来说不起作用。 - Julio Marins

9

我想提醒一下,虽然这可能不能解决你的问题,但发送到表单的“initial”字典kwargs似乎比field['field_name'].initial优先级更高。

class MyView(View):
    form = MyForm(initial={'my_field': 'first_value'})

class MyForm(Form):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['my_field'].initial = 'second_value'

my_field渲染后将初始设置为'first_value'

一些选项(不限于以下)可能是:

在初始化表单之前,在视图中确定second_value

class MyView(View):
    # determine second_value here
    form = MyForm(initial={'my_field': 'second_value'})

在调用super()之前,将initial中的first_value替换为second_value

class MyForm(Form):
    def __init__(self, *args, **kwargs):
        # determine second_value here
        if kwargs.get('initial', None):
            kwargs['initial']['my_field'] = 'second_value'
        super().__init__(*args, **kwargs)

在调用super()之前,请确保'first_value'不在kwargs['initial']中:

class MyForm(Form):
    def __init__(self, *args, **kwargs):
        if kwargs.get('initial', None):
            if kwargs['initial']['my_field']
                del(kwargs['initial']['my_field']
        super().__init__(*args, **kwargs)
        # determine second_value here
        self.fields['my_field'].initial = 'second_value'

0

这个有效:

class BarForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['state'] = forms.ChoiceField(
            required=False,
            choices=Foo.ADDRESS_STATE_CHOICES,
            disabled='disabled',
            initial='xyz',
        )

    state = forms.ChoiceField(
        label='State',
        choices=Foo.ADDRESS_STATE_CHOICES,
        initial='foo',
    )

0
在字段定义中添加initial= ""将解决您的问题。两种提出的方法都是正确的,您只需要在字段定义中定义initial= "",问题就会得到解决。

0

我曾经遇到过类似的问题,需要为名为“needs_response”的单选按钮设置初始值。通过检查self的属性并引用“declared_fields”解决了这个问题:

    # views.py
    def review_feedback_or_question(request, template, *args, **kwargs):
        if 'fqid' in kwargs:
            fqid = kwargs['fqid']
        submission = FeedbackQuestion.objects.get(pk=fqid)
        form = FeedbackQuestionResponseForm(submission_type=submission.submission_type)
        # other stuff

    # forms.py
    class FeedbackQuestionResponseForm(forms.Form):
        CHOICES = (('1', 'Yes'), ('2', 'No'))
        response_text = forms.CharField(
            required=False,
            label='',
            widget=forms.Textarea(attrs={'placeholder': 'Enter response...'}))
        needs_response = forms.ChoiceField(choices=CHOICES,
            label='Needs response?',
            widget=forms.RadioSelect())
        def __init__(self, *args, **kwargs):
            if 'submission_type' in kwargs:
                submission_type = kwargs.pop('submission_type')
                if submission_type == 'question':
                    self.declared_fields['needs_response'].initial = 1
                else:
                    self.declared_fields['needs_response'].initial = 2
            super(FeedbackQuestionResponseForm, self).__init__(*args, **kwargs)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接