Django Form Dynamic Fields从POST中遍历每个字段并创建记录



我正在寻找一些建议从这里去哪里。我一直在制作一个表单,它动态地生成它的字段。

表单正在正常工作并正确生成所有内容。然而,我有如何保存实际表单数据的问题。我正在寻找每个字段保存为模型中的新项目。

View .py中的View类

class MaintenanceCheckListForm(LoginRequiredMixin, FormView):
login_url = '/accounts/login'
template_name = 'maintenance/checklist.html'
form_class = MaintenanceCheckListForm
success_url = reverse_lazy('m-checklist')
def form_valid(self, form):
form.cleaned_data
for key, values in form:
MaintenanceCheckList.objects.create(
item = key,
is_compliant = values
)
return super().form_valid(form)

from forms.py

class MaintenanceCheckListForm(forms.Form):
def __init__(self, *args, **kwargs):
super(MaintenanceCheckListForm, self).__init__(*args, **kwargs)

items = Maintenance_Item.objects.all()
CHOICES = (
('P','Compliant'),
('F','Non-Compliant'),
)
for item in items:
self.fields[str(item.name)] = forms.ChoiceField(
label=item.name,
choices=CHOICES,
widget=forms.RadioSelect,
initial='F',
)

The Model, from models.py

class MaintenanceCheckList(CommonInfo):
CHOICES = (
('P','Compliant'),
('F','Non-Compliant'),
)
id = models.AutoField(primary_key=True)
item = models.CharField(max_length=100)
is_compliant = models.CharField(max_length=20, choices= CHOICES)

当它POST的时候,我有麻烦从表单访问数据。我已经做了一些故障排除,我在"'form_valid''中静态地设置了值,并且似乎在模型中生成了正确的整体数量。但是,当我试图插入POST中的值时,问题就开始了。

我收到以下错误,我认为它试图将所有键和值转储到单个项中,而不是循环遍历每个键、值并创建项。

DataError at /maintenance/checklist
value too long for type character varying(100)
Request Method: POST
Request URL:    http://t1.localhost:8000/maintenance/checklist
Django Version: 3.1.6
Exception Type: DataError
Exception Value:    
value too long for type character varying(100)

我对Django的世界是相当陌生的(4周到目前为止,可能是12周的python)。所以任何帮助都会很棒!

我相信你有点跑题了。有一个更简单的解决方案,就是使用Model格式集来满足你的需要。

首先,如果你想要一个自定义表单,输入:

from django import forms

class MaintenanceCheckListComplianceForm(forms.ModelForm):
item = forms.CharField(widget = forms.HiddenInput())
is_compliant = forms.ChoiceField(
choices=MaintenanceCheckList.CHOICES,
widget=forms.RadioSelect,
initial='F',
)

class Meta:
model = MaintenanceCheckList
fields = ('item', 'is_compliant')

接下来在视图中与modelformset_factory一起使用:

from django.forms import modelformset_factory

class MaintenanceCheckListFormView(LoginRequiredMixin, FormView): # Changed view name was a bit misleading
login_url = '/accounts/login'
template_name = 'maintenance/checklist.html'
success_url = reverse_lazy('m-checklist')

def form_valid(self, form):
instances = form.save()
return super().form_valid(form)

def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['queryset'] = MaintenanceCheckList.objects.none()
kwargs['initial'] = [{'item': obj['name'], 'is_compliant': 'F'} for obj in Maintenance_Item.objects.all().values('name')]
return kwargs

def get_form(self, form_class=None):
kwargs = self.get_form_kwargs()
extra = len(kwargs['initial'])
form_class = modelformset_factory(MaintenanceCheckList, form=MaintenanceCheckListComplianceForm, extra=extra)
return form_class(**kwargs)

现在在你的模板中:

<form method="post">
{{ form }}
</form>

或者手动渲染:

<form method="post">
{{ form.management_form }}
{% for sub_form in form %}
Item: {{ sub_form.item.value }}
{{ sub_form }}
{% endfor %}
</form>

注意:上面的用法有点奇怪,因为FormView将formset变量命名为form,你应该考虑改进一下。

注意看看实现,这样做感觉有点奇怪。我建议你重新设计一下你的模型。也许在你的模型之间有一个外键?在这个实现中,基本上感觉你有重复的数据。