Django model_formset 无法编辑、保存或删除信息
Django model_formset not able to edit, save or delete information
我正在尝试创建一个简单的模型表单集来显示同一表单的多个副本。我的 models.py table 叫做 Driver,它只有一个字段,driver:
class Driver(models.Model):
driver = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.driver if self.driver else ''
我的urls.py:
urlpatterns = [
path('driver/', DriverCreateView.as_view(), name = "driver-create"),
]
我的forms.py:
class DriverForm(forms.ModelForm):
class Meta:
model = Driver
fields = ['driver']
# exclude = ("id",)
DriverFormSet = modelformset_factory(Driver, form = DriverForm, fields = ['driver'], extra = 1, max_num=20, can_delete=True)
我很确定问题出在 views.py:
class DriverCreateView(LoginRequiredMixin, CreateView):
model = Driver
form_class = DriverForm
template_name = 'trucking/driver_form.html'
def get_context_data(self, **kwargs):
context = super(DriverCreateView, self).get_context_data(**kwargs)
context['formset'] = DriverFormSet()
return context
def post(self, request, *args, **kwargs):
formset = DriverFormSet(request.POST)
form= DriverForm(request.POST)
if formset.is_valid():
formset.save()
if self.request.POST.get('Save_Exit'):
return HttpResponseRedirect('/database/')
if self.request.POST.get('Save'):
return HttpResponseRedirect('/driver/')
return render(request, self.template_name, {'formset': formset})
最后是我的模板 driver_form.html:
<form method = "POST">
<fieldset class = "form-group">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
{% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
<table cellpadding="6" cellspacing="1" border="0">
<tbody>
{% for form in formset %}
{% for field in form.visible_fields %}
<tr>
<td class="column_name">{{field.label_tag}}{{field.auto_id}}</td>
<td class="column_data">{{field}}</td>
<td class="column_errors">{{field.errors|striptags}}</td>
</tr>
{% endfor %}
{% endfor %}
<tr>
<td colspan = "2" class="column_submit">
<input type="submit" name="Save_Exit" value="Save & Exit" class="submit">
<input type="submit" name="Save" value="Save" class="submit">
<a href="{% url 'database'%}"><input type="button" name="Cancel" value="Cancel" class="submit"></a>
</td>
</tr>
</tbody>
我认为它是 views.py 文件的原因是我从许多不同的来源拼凑了它,并且不确定我的行是否真的有必要或者我在表格中遗漏了什么实际更新信息。当我将基于 class 的视图中的 post
函数编辑为 form.save()
而不是 formset.save()
时,我将能够成功添加新字段,但无法更新或删除现有领域。我有一种感觉,逻辑没有以某种方式在 if 语句中捕获,或者表单集被重置为默认值,也许在这一行中:
context['formset'] = DriverFormSet()
如有任何建议,我们将不胜感激。
您错过了添加 formset
隐藏输入。这些输入为每个表单提供 Driver.id
,因此 django 将知道要使用哪个 driver
.
更新哪个实例
而不是
{% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
使用
{% for form in formset %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endfor %}
CreateView
(以及所有基于 class 的视图)并非设计用于处理表单集。他们应该处理 1 个表单和 1 个模型实例。您将拥有多个表单(通过表单集)和多个模型实例。您的视图会工作,但它没有充分利用 CreateView
:您没有使用应该使用的几种方法,您将拥有永远不会使用的 self.object
和 self.form
在你看来。
基于函数的视图没有错。参考django docs。例如:
@login_required
def create_drivers(request):
if request.method == 'POST':
formset = DriverFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
if request.POST.get('Save_Exit'):
return HttpResponseRedirect('/database/')
if request.POST.get('Save'):
return HttpResponseRedirect('/driver/')
else:
formset = DriverFormSet()
return render(request, 'trucking/driver_form.html', {'formset': formset})
我正在尝试创建一个简单的模型表单集来显示同一表单的多个副本。我的 models.py table 叫做 Driver,它只有一个字段,driver:
class Driver(models.Model):
driver = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.driver if self.driver else ''
我的urls.py:
urlpatterns = [
path('driver/', DriverCreateView.as_view(), name = "driver-create"),
]
我的forms.py:
class DriverForm(forms.ModelForm):
class Meta:
model = Driver
fields = ['driver']
# exclude = ("id",)
DriverFormSet = modelformset_factory(Driver, form = DriverForm, fields = ['driver'], extra = 1, max_num=20, can_delete=True)
我很确定问题出在 views.py:
class DriverCreateView(LoginRequiredMixin, CreateView):
model = Driver
form_class = DriverForm
template_name = 'trucking/driver_form.html'
def get_context_data(self, **kwargs):
context = super(DriverCreateView, self).get_context_data(**kwargs)
context['formset'] = DriverFormSet()
return context
def post(self, request, *args, **kwargs):
formset = DriverFormSet(request.POST)
form= DriverForm(request.POST)
if formset.is_valid():
formset.save()
if self.request.POST.get('Save_Exit'):
return HttpResponseRedirect('/database/')
if self.request.POST.get('Save'):
return HttpResponseRedirect('/driver/')
return render(request, self.template_name, {'formset': formset})
最后是我的模板 driver_form.html:
<form method = "POST">
<fieldset class = "form-group">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.non_form_errors }}
{% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
<table cellpadding="6" cellspacing="1" border="0">
<tbody>
{% for form in formset %}
{% for field in form.visible_fields %}
<tr>
<td class="column_name">{{field.label_tag}}{{field.auto_id}}</td>
<td class="column_data">{{field}}</td>
<td class="column_errors">{{field.errors|striptags}}</td>
</tr>
{% endfor %}
{% endfor %}
<tr>
<td colspan = "2" class="column_submit">
<input type="submit" name="Save_Exit" value="Save & Exit" class="submit">
<input type="submit" name="Save" value="Save" class="submit">
<a href="{% url 'database'%}"><input type="button" name="Cancel" value="Cancel" class="submit"></a>
</td>
</tr>
</tbody>
我认为它是 views.py 文件的原因是我从许多不同的来源拼凑了它,并且不确定我的行是否真的有必要或者我在表格中遗漏了什么实际更新信息。当我将基于 class 的视图中的 post
函数编辑为 form.save()
而不是 formset.save()
时,我将能够成功添加新字段,但无法更新或删除现有领域。我有一种感觉,逻辑没有以某种方式在 if 语句中捕获,或者表单集被重置为默认值,也许在这一行中:
context['formset'] = DriverFormSet()
如有任何建议,我们将不胜感激。
您错过了添加 formset
隐藏输入。这些输入为每个表单提供 Driver.id
,因此 django 将知道要使用哪个 driver
.
而不是
{% for hidden in form.hidden_fields %} {{ hidden }} {% endfor %}
使用
{% for form in formset %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endfor %}
CreateView
(以及所有基于 class 的视图)并非设计用于处理表单集。他们应该处理 1 个表单和 1 个模型实例。您将拥有多个表单(通过表单集)和多个模型实例。您的视图会工作,但它没有充分利用 CreateView
:您没有使用应该使用的几种方法,您将拥有永远不会使用的 self.object
和 self.form
在你看来。
基于函数的视图没有错。参考django docs。例如:
@login_required
def create_drivers(request):
if request.method == 'POST':
formset = DriverFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
if request.POST.get('Save_Exit'):
return HttpResponseRedirect('/database/')
if request.POST.get('Save'):
return HttpResponseRedirect('/driver/')
else:
formset = DriverFormSet()
return render(request, 'trucking/driver_form.html', {'formset': formset})