I am adding custom validation to my forms and custom fields in my Django app. I would like to be able to modify the value of a field when triggering an error. For example, i
We can't redireclty edit request.data
because it's an immutable dict. You need to copy it, do your stuff and return it.
But after differentes solutions I find this way (tested in Django 2.2.6)
class MyForm(ModelForm):
def clean(self):
cleaned_data = super(MyForm, self).clean()
self.instance.field = 'value'
return cleaned_data
If your form is a model form a better approach would be to get an instance and correct that data instead:
inst = my_form.save(commit=False)
if inst.a34_stuff is None: #or incorrect
inst.a34_stuff = "corrected"
request.user.message_set.create(message = "Error corrected")
return HttpResponseRedirect(reverse('your_url_name',
args=[])
PS: I am not sure if this will actually work... Not sure if form will pickup changes.
change self data in the clean method to change the value which gets displayed
It is possible to modify a value of a field during clean()
if you update self.data
attribute of a Form. self.data
is an instance of the QueryDict class. By default, querydicts are immutable. To make them mutable, you should use .copy()
method. From the documentation:
The QueryDicts at request.POST and request.GET will be immutable when accessed in a normal request/response cycle. To get a mutable version you need to use QueryDict.copy()
self.data = self.data.copy()
self.data['your_field'] = 'new value'
This is the way I've tried and works for me:
inst = my_form.save(commit=False)
if not inst.a34_stuff: # or incorrect
inst.data["a34_stuff"] = "corrected"
I was setting a value to a specific field in another clean function, but it didnt work because of it was overwrited by the main clean function. In order to set the value and keep it :
def clean_tipo_cupon(self):
tipo_cupon = self.cleaned_data['tipo_cupon']
qscu = mdlcat.TipoCuponVenta.objects.filter(
id=tipo_cupon, estado_id=1,
)
if not qscu.exists():
wmessage = u'introducido no paso validación'
raise forms.ValidationError(wmessage)
qscu = qscu.first()
if not qscu.default_owner is None:
self.cleaned_data['default_owner'] = qscu.default_owner.id
return tipo_cupon
def clean(self):
cleaned_data = super().clean()
for item in self.fields.keys():
if isinstance(cleaned_data.get(item), str):
cleaned_data[item] = cleaned_data.get(item).upper()
# if a default owner is configured by coupon type
# it will be assigned
tipo_cupon = cleaned_data['tipo_cupon']
qscu = mdlcat.TipoCuponVenta.objects.filter(
id=tipo_cupon, estado_id=1,
)
qscu = qscu.first()
if not qscu.default_owner is None:
self.cleaned_data['default_owner'] = qscu.default_owner.id
return cleaned_data