Формы обновления Django не сохраняются
Простая база данных рецептов с формой обновления, но при добавлении нового ингредиента в существующий рецепт, он не сохраняет обновление. Я не получаю никакого сообщения об ошибке.
Установка: пользователь заходит в список рецептов и ему представляется кнопка создания новых рецептов и список существующих рецептов с кнопкой обновления рядом с названием рецепта. Когда пользователь нажимает кнопку обновления, он переходит на страницу /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 %}
Разобрался... наконец-то. Сначала я решил, что причина того, что он не сохраняется, в том, что он не проходит проверку 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.']}, {}, {}, {}]
Googling formset this field is required, I came across this article: 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>