Django表单动态字段从POST循环到每个字段并创建记录

2024-06-28 20:25:10 发布

您现在位置:Python中文网/ 问答频道 /正文

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

表单正在运行并正确生成所有内容。但是,我在如何保存实际表单数据方面遇到了问题。我正在寻找每个字段保存为模型中的新项

来自View.py的视图类

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)

来自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',
        )

模型,来自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)

当表单发布时,我无法从表单中访问数据。我已经做了一些故障排除,在“form\u valid”中静态地设置了值,它似乎在模型中生成了正确数量的entires。然而,当我尝试从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周,到目前为止还在计算中,在python中可能还有12周)。因此,任何援助都将是惊人的


Tags: namepy模型selfform表单formodels
1条回答
网友
1楼 · 发布于 2024-06-28 20:25:10

我相信你有点走火入魔了。有一个更简单的解决方案,就是使用Model formsets来满足您的需求

首先,如果需要自定义表单,请执行以下操作:

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。您应该考虑对此进行一些改进

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

相关问题 更多 >