Django form dynamically created fields miss from cleaned_data
I'm trying to implement dynamic fields in ModelForm
using AJAX requests.
I have a cameras_num
custom field as IntegerField
. Once user picks value AJAX passes cameras_num
field's value to ModelForm
with kwargs and generates forms.ModelChoiceField
with names camera_{number}
("camera_1", "camera_2" ... "camera_3").
However when form submits form.data
contains all "cameras" (lets say {"camera_1": [1], "camera_2": [2]}
) while form.cleaned_data
contains only one camera ("camera_1").
class ConfigurationForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
cameras_qty = kwargs.pop('cameras_qty', 1)
super(ConfigurationForm, self).__init__(*args, **kwargs)
if cameras_qty:
for camera_num in range(1, cameras_qty+1):
self.fields[f"camera_{camera_num}"] = forms.ModelChoiceField(
label=f"Camera {camera_num}",
queryset=models.Camera.objects.all()
)
cameras_num = forms.IntegerField(
widget=forms.Select(choices=[(i,i) for i in range(1, 4)]),
initial=1
)
view.py
:
def create_device_view(request):
if request.method == "POST":
device_config_form = forms.ConfigurationForm(request.POST)
# here device_config_form.data contains all "cameras"
if device_config_form.is_valid():
# here only "camera_1" exists in device_config_form.cleaned_data
device_config_form.save()
return redirect(reverse("device_list", kwargs={"status": "all"}))
else:
device_config_form = forms.ConfigurationForm()
if is_ajax(request):
# cameras
cameras_qty = request.GET.get("cameras_qty")
if cameras_qty and isinstance(cameras_qty, str):
cameras_data = []
# passing cameras qty received from GET parameters
device_config_form = forms.ConfigurationForm(cameras_qty=int(cameras_qty))
for field_name in device_config_form.fields.keys():
if field_name.startswith("camera_"):
camera_field = (
device_config_form[field_name].label_tag(),
str(device_config_form[field_name])
)
cameras_data.append(camera_field)
return JsonResponse(
data={"success": True, "cameras": cameras_data},
safe=False
)
return render(
request,
"production/device_create.html",
{"device_config_form": device_config_form})