【问题标题】:Django update formset not savingDjango更新表单集不保存
【发布时间】:2021-12-30 17:30:11
【问题描述】:

带有更新表单的简单配方数据库,但是当向现有配方添加新成分时,它不会保存更新。我也没有收到任何错误消息。

设置是用户进入一个配方列表,并显示一个用于新配方的创建按钮和一个现有配方列表以及配方名称旁边的更新按钮。当用户单击更新按钮时,它会将他们带到 /recipe_update/#/ 并显示成分列表。它应该允许他们添加/删除/更改成分和百分比,然后保存更改,但它不会保存新的成分或更改。

models.py

class Recipe(models.Model):
    name = models.CharField(max_length=200, null=True)
    description = models.CharField(max_length=200, null=True, blank=True)

    def __str__(self):
        return self.name

class Recipe_Ingredient(models.Model):
    recipe_name = models.ForeignKey(Recipe, null=True, on_delete = models.SET_NULL)
    ingredient = models.ForeignKey(Product, null=True, on_delete= models.SET_NULL)
    recipe_percent = models.DecimalField(max_digits=8, decimal_places=5, blank=True)

views.py

def recipeUpdate(request, recipe_id):
    recipe = Recipe.objects.get(pk=recipe_id)
    recipeingredient = inlineformset_factory(Recipe, Recipe_Ingredient, fields=('ingredient', 'recipe_percent',))
        
    if request.method == 'POST':
        formset = recipeingredient(request.POST, instance=recipe)
        if formset.is_valid():
            formset.save()
            return redirect('/')

    formset = recipeingredient(instance=recipe)
    context = {'formset':formset}
    return render(request, 'accounts/recipe_form.html', context)

urls.py

...
    path('recipe_update/<recipe_id>/', views.recipeUpdate, name="recipe_update"),
...

recipe_form.html

{%  extends 'accounts/main.html' %}
{% load static %}
{% block content %}


<div class="row">
    <div class="col-md-6">
        <div class="card card-body">
            <form action="" method="POST">
                {% csrf_token %}
                {{ form }}


                {{ formset.management_form }}

                <table>
                    {{ form.id }}
                    {% for p in formset %}
                        <tr>
                        {% if forloop.first %}
                            <td>{{ p.DELETE.label_tag }}</td>
                            <td>{{ p.ingredient.label_tag }}</td>
                            <td>{{ p.recipe_percent.label_tag }}</td>
                            <p></p>
                        {% endif %}
                        </tr>
                        <!--{{ p.id }}
                        {{ p.ORDER }}-->
                        <tr></tr>
                        <td>{{ p.DELETE }}</td>
                        <td>{{ p.ingredient }}</td>
                        <td>{{ p.recipe_percent }}</td>
                        </tr>
                    {% endfor %}
                </table>

                <input type="submit" name="Submit">
            </form>



        </div>
    </div>
</div>


{% endblock %}

【问题讨论】:

  • 我不确定,但问题可能出在表单中的空 action 属性中。按照here 的建议尝试忽略它,然后重试
  • 这不是解决方案。奇怪的是,如果我只是在模板中添加 {{ formset }},它就可以正常工作,但是如果我将其更改为 {{ formset.management_form }} 然后执行循环逻辑,它就不起作用了。所以我想弄清楚两者之间的区别。

标签: django django-forms


【解决方案1】:

想通了……终于。 起初,我发现它没有保存的原因是它没有通过 formset.is_valid 检查,所以我添加了一个

        else:
            print(formset.errors)

到views.py,发现我的错误是

[31/Dec/2021 15:08:20] "POST /recipe_update/1/ HTTP/1.1" 200 276978
[{'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {'id': ['This field is required.']}, {}, {}, {}]

谷歌表单集这个字段是必需的,我遇到了这篇文章: django formset not validating because ID is required

解决问题的方法是在我的 for 循环中,我添加了 {{p.id}}。

<table>
                    {% for p in formset %}
                        {{ p.id }}
                        <tr>
                        {% if forloop.first %}
                            <td>{{ p.DELETE.label_tag }}</td>
                            <td>{{ p.ingredient.label_tag }}</td>
                            <td>{{ p.recipe_percent.label_tag }}</td>
                            <p></p>
                        {% endif %}
                        </tr>
                        <!--{{ p.id }}
                        {{ p.ORDER }}-->
                        <tr></tr>
                        <td>{{ p.DELETE }}</td>
                        <td>{{ p.ingredient }}</td>
                        <td>{{ p.recipe_percent }}</td>
                        </tr>
                    {% endfor %}
                </table>

【讨论】: