问题
I have a custom Django 1.11 Widget
that allows for a dynamic number of key/value pairs to be entered into a form, which are assembled into a dict
by the widget's value_from_datadict
method. When I check the form's cleaned_data
, I see exactly what I'm expecting:
{'fieldname': {'key1': 'value1', ....}
However, when the form is saved, fieldname
isn't being updated. I've traced this down to the implementation of django.forms.models.construct_instance
:
def construct_instance(form, instance, fields=None, exclude=None):
"""
Constructs and returns a model instance from the bound ``form``'s
``cleaned_data``, but does not save the returned instance to the
database.
"""
from django.db import models
opts = instance._meta
cleaned_data = form.cleaned_data
file_field_list = []
for f in opts.fields:
if not f.editable or isinstance(f, models.AutoField) \
or f.name not in cleaned_data:
continue
if fields is not None and f.name not in fields:
continue
if exclude and f.name in exclude:
continue
# Leave defaults for fields that aren't in POST data, except for
# checkbox inputs because they don't appear in POST data if not checked.
if (f.has_default() and
form[f.name].field.widget.value_omitted_from_data(form.data, form.files, form.add_prefix(f.name))):
continue
# Defer saving file-type fields until after the other fields, so a
# callable upload_to can use the values from other fields.
if isinstance(f, models.FileField):
file_field_list.append(f)
else:
f.save_form_data(instance, cleaned_data[f.name])
for f in file_field_list:
f.save_form_data(instance, cleaned_data[f.name])
return instance
Its stated purpose is to create an instance from the cleaned data of a form. However, this line causes problems for me:
if (f.has_default() and
form[f.name].field.widget.value_omitted_from_data(form.data, form.files, form.add_prefix(f.name))):
continue
It skips fields if the POST data doesn't contain the name of the field. Because I have a more complex set of inputs on HTML side of the form, that field name doesn't actually exist in it. So even though the field exists in cleaned_data
, it will never be updated. The simple workaround is to add a hidden input with the correct name on the form, but this seems unnecessarily hacky.
I'm curious: what is the rationale for checking against the POST data at this point? Is the issue how I'm dynamically constructing complex fields in the front end?
来源:https://stackoverflow.com/questions/54661557/instance-construction-fails-on-form-data-check