【问题标题】:Modify value of a Django form field during clean() and validate again在 clean() 期间修改 Django 表单字段的值并再次验证
【发布时间】:2018-04-01 04:33:36
【问题描述】:

我想做这样的事情:

class UsuarioForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        super(UsuarioForm, self).__init__(*args, **kwargs)
        self.fields['cpf'].widget.attrs['maxlength'] = 14
        self.fields['telefone'].widget.attrs['maxlength'] = 15
        self.fields['celular'].widget.attrs['maxlength'] = 15



    nome = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
                                                         'icone': 'fa fa-font'}))

    usuario = forms.CharField(widget=forms.TextInput(attrs={'readonly': True,
                                                         'icone': 'fa fa-user'}))



    def clean(self):

        cleaned_data = self.cleaned_data

        self.data['cpf'] = re.sub("[\.-]", "", self.data['cpf'])

        clean_data_again_to_revalidate_the_field


    class Meta:
        model = Usuario

        exclude = ['codigo', 'estabelecimento', 'dono', 'data', 'estabelecimento', 'cargo', 'usuario']


        widgets = {

            'cpf': forms.TextInput(attrs={'placeholder': Text().cpf(),
                                          'icone': 'fa fa-credit-card',
                                          'id':'cpf',

                                          }),

            'telefone': forms.TextInput(attrs={'placeholder': Text().telefone(),
                                               'icone': 'fa fa-phone'.decode('utf-8'),
                                               'id': Text().telefone()}),

            'celular': forms.TextInput(attrs={'placeholder': Text().celular(),
                                              'icone': 'fa fa-mobile',
                                              'id': Text().celular()}),
        }

我想更改字段 CPF 以删除点。之后,我想再次验证该字段。有可能吗?

另外,接收值的 self.data['cpf'] 是不可能的。它失败了:这个 QueryDict 实例是不可变的。

我创建了方法 clean_cpf,但它从未被调用过。我认为是因为cpf字段没有出现在cleaned_data中,因为在我接收数据的格式中是无效的。

另外,cpf 不在cleaned_data 中。我认为因为是无效的。 cpf 的最大长度为 11,但是当它来自屏幕时,该字段有 14 个字符。这就是为什么我需要更改该字段并再次验证它。

【问题讨论】:

  • 如果 QueryDict 实例是不可变的。在用不同的值重新分配它之前尝试self.data._mutable = True 然后self.data['cpf'] = re.sub("[\.-]", "", self.data['cpf']) 尽管这应该不太受欢迎。
  • @ArpitGoyal QueryDict._mutable 是一个受保护的属性,你不应该碰它(除非你真的知道你在做什么并且没有其他明智的解决方案)。在这种情况下,有一个 记录 正确的方法来获取可变 QueryDict :“要获取可变版本,您需要使用 QueryDict.copy()”
  • @DiegoMartins :如果链接的问题不能解决您的问题,请发表评论解释原因 - 也许您需要自定义 FormField,或者您最好接受与正则表达式匹配的虚线值...
  • @bruno desthuilliers 我解释了。该链接建议使用 clean_cpf 方法。但是他的方法永远不会被调用,因为 cpf 无效。我认为由于文档中的原因没有调用该方法:如果任何时候任何方法引发 ValidationError,验证将停止并引发该错误link
  • @DiegoMartins 好点,应该更深入地阅读,抱歉。

标签: python django modelform


【解决方案1】:

q&d hack 是直接在表单的__init__ 中修复data 中的值(nb:未经测试的代码):

class UsuarioForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(UsuarioForm, self).__init__(*args, **kwargs)
        if self.data:
            # make the QueryDict mutable
            self.data = self.data.copy()
            # remove dots from data["cpf"]
            if "cpf" in self.data:
                self.data["cpf"] = self.data["cpf"].replace(".", "")
        # ...

但如果您仍然遇到验证错误,则在重新显示表单时,“cpf”字段的数据将呈现不带点的渲染器。

更简洁的解决方案是使用自定义的“CreditCard”字段,因为您的 cpf 字段似乎需要信用卡号。网络上有几个第三方实现,可以开箱即用,或者至少提供一个起点。

附带说明:您覆盖表单Meta 中的默认小部件,然后覆盖表单__init__ 中相同字段的“max_length”,这不是很干。您应该直接在Meta.widgets 部分设置最大长度。

【讨论】:

  • 非常感谢。它成功了,我能够在验证之前修改 CPF 并且模型表格正在工作。非常感谢。
猜你喜欢
  • 2010-10-13
  • 2012-01-24
  • 2011-02-24
  • 2016-04-29
  • 1970-01-01
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多