使用 django cleaned data pop 在提交到 db 之前删除数据

using django cleaned data pop to remove data before commit to db

我有一个带有 select 列表的表单。

当用户 select 从 award_grant_type select 列表中输入 8888 或 9999 的值时,我想要表单输入字段中可能存在或不存在的一些数据(用户可能已经在表单文本输入字段中输入了数据,然后 selected 8888 或 9999)在表单数据提交到数据库之前被删除。

所以我有以下 model.py 代码:

.....
DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITH_PROMPT = 8888
DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITHOUT_PROMPT = 9999
.....

AWARD_GRANT_TYPES = (
    (SELECT_AWARD_AND_GRANT_TYPE, _('Select Type')),
    (AWARD, _('Award')),
    (GRANT, _('Grant')),
    (TRAVEL_GRANT, _('Travel Grant')),
    (OTHER_AWARD, _('Other Award')),
    (OTHER_GRANT, _('Other Grant')),
    (WRITE_MY_OWN_AWARD_AND_GRANT_TYPE_DESCRIPTION, _('Write my own Type description')),  #7777
    (DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITH_PROMPT, _('Display only Description with prompt')),  #8888
    (DISPLAY_ONLY_AWARD_AND_GRANT_DESCRIPTION_WITHOUT_PROMPT, _('Display only Description without prompt')) #9999
)

user = models.ForeignKey(User)
language_version = models.ForeignKey('LanguageVersion')
award_grant_type = models.PositiveIntegerField(choices=AWARD_GRANT_TYPES, default=SELECT_AWARD_AND_GRANT_TYPE, validators=[MinValueValidator(1)])
award_grant_type_description = models.CharField(null=True, blank=True, max_length=250)
award_grant_date = models.DateField(null=True, blank=True)
award_grant_description = models.TextField(null=False, blank=False, max_length=5000)

这是我的 forms.py 干净代码,当用户从 select 中输入 8888 或 9999 时,应该删除 award_grant_type_descriptionaward_grant_date 字段] 在提交到数据库之前列出 award_grant_type:

def clean(self):

    cd_agdf = super(AwardGrantDetailsForm, self).clean()

    if 'award_grant_type' in cd_agdf:
        if cd_agdf['award_grant_type'] == '':
            self._errors['award_grant_type'] = self.error_class([_("You must select a Type.")])

        elif cd_agdf['award_grant_type'] == 8888 or cd_agdf['award_grant_type'] == 9999:
            #  remove the entered values when the award grant type only requires minimum data.
            self.cleaned_data.pop('award_grant_type_description', None)
            self.cleaned_data.pop('award_grant_date', None)
        else:
            ....
    return cd_agdf

任何人都可以指出我做错了什么吗? 在表单数据提交到数据库之前,award_grant_type_descriptionaward_grant_date 没有被删除。

编辑/更新

只有在更新现有记录时才会出现此问题。在将表单保存到数据库之前,新记录会根据需要删除数据。当现有记录有一个日期字段作为数据库记录的一部分并且 award_grant_type 从 1 更改为 8888 或 9999 时,award_grant_date 不会从数据库中删除。我想不通为什么。

第二次编辑

我已经发布了一个相关主题

尝试将 self.cleaned_data 更改为 cd_agdf。字典,那个方法cleanreturns,将被用作cleaned_data。您从 self.cleaned_data 中弹出项目,但返回时未更改 cd_ahdf。这被描述为 here(请参阅以 "The form's subclass..." 开头的最后一步)。

而不是self.cleaned_data.pop() 在将 cd_agdf 分配给 superclass

时执行 cd_agdf.pop()

仅回答编辑:数据的含义存在争议。

表单验证首先发生,其目的是解析提交的数据,清理数据并指出数据中的任何错误。此步骤的结果应该是数据的清理规范形式。

Then action:如果有效,则对表单进行操作。您解释该数据以采取适当的行动。在这里,将其写入数据库。

你的两个步骤在数据的含义上存在分歧。验证从最终数据中删除 award_grant_type_descriptionaward_grant_date,表示 “删除那些字段”。然后,该操作将缺失数据解释为 “保留该字段原样”(这是默认值 ModelForm.save() 所做的)。

您的选择:要么符合 ModelForm 的约定并将字段设置为 None 而不是删除它们,要么覆盖表单的 save() 以便它将缺失数据解释为 “从对象中删除”。除非我有充分的理由改变 ModelForm 的语义,否则我会将字段设置为 None.

我终于想通了这个问题。

当我用引号括起这些值时,问题就解决了。

这是我使用的有效示例代码:

 elif cd_agdf['award_grant_type'] == '8888' or cd_agdf['award_grant_type'] == '9999':

我希望这会对某人有所帮助。