【问题标题】:Django model_formset not able to edit, save or delete informationDjango model_formset 无法编辑、保存或删除信息
【发布时间】:2021-11-23 12:07:34
【问题描述】:

我正在尝试创建一个简单的模型表单集来显示同一表单的多个副本。我的 models.py 表名为 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 文件的原因是我从多个不同的来源拼凑而成,并不确定我拥有的行是否真的有必要,或者我在表单中缺少什么来实际更新信息.当我将基于类的视图中的post 函数编辑为form.save() 而不是formset.save() 时,我将能够成功添加新字段,但不能更新或删除现有字段。我感觉逻辑没有以某种方式在 if 语句中被捕获,或者表单集被重置为默认值,可能在这一行中:

    context['formset'] = DriverFormSet()

感谢任何建议。

【问题讨论】:

    标签: django django-forms django-class-based-views


    【解决方案1】:

    您错过了添加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(以及所有基于类的视图)并非旨在处理表单集。他们应该处理 1 个表单和 1 个模型实例。您将拥有多个表单(通过 formset)和多个模型实例。您的视图将起作用,但它没有充分利用 CreateView:您没有使用应该使用的几种方法,您将拥有 self.objectself.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})
    

    【讨论】:

    • 这很好用,谢谢。如果您不介意,还有一个问题:在每个表单字段旁边,我想写驱动程序 1:、驱动程序 2:等。我尝试使用以下代码行来执行此操作:{{field.label_tag}}{{field.auto_id}},但它返回Driver:id_form-2-driver如果我尝试使用{{field.id}},它不会返回任何内容。我怎样才能返回 id 呢?欣赏它
    • 最简单的方法是使用loop index,比如{{ field.label_tag }} {{ forloop.parentloop.counter }}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-18
    • 1970-01-01
    • 2013-02-13
    • 1970-01-01
    • 2017-11-17
    相关资源
    最近更新 更多