如何为modelForm选择字段更改empty_label?

CQP*_*CQP 17 django django-forms

我在我的一个模型中有一个字段,如下所示:

 payrollProvider = models.CharField(max_length=2, choices=PAYROLL_CHOICES)
 PAYROLL_CHOICES = (
        ('C1', 'Choice1'),
        ('C2', 'Choice2')
        etc.....
                    )
Run Code Online (Sandbox Code Playgroud)

当我为该字段创建模型表单时,Django正确生成HTML选择框,但包含默认空白值"---------".

我想知道如何将此默认值更改为其他文本,例如"请选择值".

我相信我应该可以通过以下方式在我的模型表单的init中设置它,如本答案和其他几个文档中所述:

self.fields['payrollProvider'].empty_label = "please choose value"
Run Code Online (Sandbox Code Playgroud)

但是,这对我不起作用.当我在表单的init中包含该行时,"--------"仍然显示为选择框中的初始选项.我正在粘贴下面的相关forms.py,但似乎其他人也无法访问/修改empty_label.在这个链接中,提问者描述了一种删除默认empty_label值的方法(我能够通过他的方法成功完成),但我真正想做的是修改显示的empty_label.

有任何想法吗?

这是forms.py中表单的代码,其中empty_label代码在更改默认值"----------"时未成功:

class PayrollCredentialForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PayrollCredentialForm, self).__init__(*args, **kwargs)
        self.fields['payrollUsername'].widget.attrs.update({'class' : 'yp-signup'})
        self.fields['payrollPassword'].widget.attrs.update({'class' : 'yp-signup'})
        self.fields['payrollProvider'].widget.attrs.update({'class' : 'yp-signup'})
        self.fields['payrollUsername'].widget.attrs.update({'placeholder' : '  Payroll Username'})
        self.fields['payrollPassword'].widget.attrs.update({'placeholder' : '  Payroll Password'})
        self.fields['payrollProvider'].empty_label = "please choose value"


class Meta:
    model = Company
    fields = ('payrollProvider', 'payrollUsername', 'payrollPassword')
    widgets = {
        'payrollPassword': forms.PasswordInput(),
    }
Run Code Online (Sandbox Code Playgroud)

pyt*_*pro 11

dokkaebi,这将无法正常工作.您将收到以下选择代码:

<select name="payrollProvider" id="id_payrollProvider">
<option value="" selected="selected">---------</option>
<option value="" selected="selected">please choose value</option>
<option value="C1">Choice1</option>
<option value="C2">Choice2</option>
</select>
Run Code Online (Sandbox Code Playgroud)

我想到的唯一相对方便的方法是在表单中做这样的事情:

class PayrollCredentialForm(forms.ModelForm):
    class Meta:
        model = Company
    def __init__(self, *args, **kwargs):
        super(PayrollCredentialForm, self).__init__(*args, **kwargs)
        self.fields["payrollProvider"].choices = [("", "please choose value"),] + list(self.fields["payrollProvider"].choices)[1:] 
Run Code Online (Sandbox Code Playgroud)


Dam*_*nic 7

实际上,现在(从Django 1.8和更高版本)覆盖empty_label作品:

class PayrollCredentialForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(PayrollCredentialForm, self).__init__(*args, **kwargs)
        self.fields['payrollProvider'].empty_label = 'Please, choose value'
Run Code Online (Sandbox Code Playgroud)

此外,如果您使用Django Admin,则可以选择为列表视图设置空值:

class PayrollCredentialAdmin(admin.ModelAdmin):
    list_display = ('payrollProvider_value', )

    def payrollProvider_value(self, instance):
        return instance.payrollProvider
    payrollProvider_value.empty_value_display = 'Empty value'
Run Code Online (Sandbox Code Playgroud)

如果字段应该readonly怎么办?

如果以这种方式修改字段应该是一个问题readonly.

如果readonly_fieldsPayrollCredentialAdmin类中的属性中指定了重写的表单字段,则会导致KeyError异常PayrollCredentialForm(因为readonly字段不会包含在表单中self.fields).要处理这个问题,需要覆盖formfield_for_dbfield而不是使用readonly_fields:

def formfield_for_dbfield(self, db_field, **kwargs):
    field = super(PayrollCredentialAdmin, self).formfield_for_dbfield(
        db_field, **kwargs
    )
    db_fieldname = canonical_fieldname(db_field)

    if db_fieldname == 'payrollProvider':
        field.widget = forms.Select(attrs={
            'readonly': True, 'disabled': 'disabled',
        })

    return field
Run Code Online (Sandbox Code Playgroud)

可能有用.


Django 更新1.11:

下面的评论假设这种覆盖对于较新版本的Django不再有效.


jon*_*man 6

问题是您正在尝试指定"选择"字段类型不可用的内容.

empty_label选项适用于forms.ModelChoiceField,它恰好使用Select小部件,但与您为其提供选项的CharField不是同一类型的字段.

https://docs.djangoproject.com/en/dev/ref/forms/fields/#modelchoicefield

您也可以在上一个问题中看到这一点:https://stackoverflow.com/a/740011/1406860

您可以尝试覆盖模型窗体的html,将第一个选项添加为"请选择值".或者,您可以使用模板过滤器来执行相同的操作.最后,您可以和("","请选择值")到PAYROLL_CHOICES,如果您不希望在没有payrollProvider的情况下提交它,只需为模型中的字段设置blank = False.

JD