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

你。 提交于 2019-12-23 14:02:11

问题


I have a form with a select list.

When the user selects a value of 8888 or 9999 from the award_grant_type select list, I want some of the data that may or may not exist in the form input fields (the user may have entered data into the form text input fields and then selected 8888 or 9999) to be deleted before the form data is commited to the database.

So I have the following model.py code:

.....
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)

Here is my forms.py clean code that should remove the award_grant_type_description and award_grant_date fields when the user has selected 8888 or 9999 from the select list award_grant_type before being committed to the db:

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

Can anyone point out what I have done incorrectly? The award_grant_type_description and award_grant_date are not removed before the form data is committed to the db.

EDIT / UPDATE

This issue only occurs when the existing record is updated. A new record removes the data as required before the form is saved to the db. When an existing record has a date field as part of the db record and the award_grant_type is changed from say 1 to 8888 or 9999, then the award_grant_date is NOT removed from the db. I cannot figure out why.

2nd EDIT

I have posted a related thread here.


回答1:


Try to change self.cleaned_data to cd_agdf. Dictionary, that method clean returns, will be used as cleaned_data. You popped items from self.cleaned_data, but returned not changed cd_ahdf. This is described here (see last step starting with "The form's subclass...").




回答2:


Answering to the edit only: there is a fight over what the data means.

Form validation happens first, its purpose is to parse the submitted data, clean it up and point any error in the data. The result of this step should be the cleaned up, canonical form of the data.

Then action: if valid, form is acted upon. You interpret that data to take appropriate action. Here, writing it to a database.

Your two steps disagree on the meaning of data. Validation removes award_grant_type_description and award_grant_date from the final data to mean “blank out those fields”. Then, the action interprets missing data as “leave that field as it is” (that's what the default ModelForm.save() does).

Your choice: either conform to ModelForm's convention and set the fields to None instead of removing them, or override your form's save() so it interprets missing data as “remove from object”. Unless I had a good reason to alter ModelForm's semantics, I'd go with setting the fields to None.




回答3:


I finally figured this issue out.

When I wrap the values in quotation marks, the issue is resolved.

Here is the example code I used that works:

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

I hope that this will help someone.




回答4:


instead of self.cleaned_data.pop() do cd_agdf.pop() as you are assigning cd_agdf to superclass



来源:https://stackoverflow.com/questions/31134274/using-django-cleaned-data-pop-to-remove-data-before-commit-to-db

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!