0

Simple recipe database with an update form, but when adding a new ingredient to an existing recipe, it's not saving the update. I'm not getting any error message either.

The setup is user goes go a recipe list and is presented with a create button for new recipes and a list of existing recipes with an update button next to the recipe name. When the user clicks the update button, it takes them to /recipe_update/#/ and is presented with the list of ingredients. It should allow them to add/remove/change ingredients and percent, and then save the changes, but it's not saving new ingredients or changes.

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 %}
  • I am not sure, but the problem may be in empty `action` attribute in your form. Try leaving it out, as suggested [here](https://stackoverflow.com/a/1132015/11544538) and try again – Ersain Dec 30 '21 at 19:10
  • That wasn't the solution. What's weird, is if I just add {{ formset }} in my template, it works just fine, but if I change it to {{ formset.management_form }} and then do the looping logic, it doesn't work. So I'm trying to figure out the difference between the two. – James Behling Dec 31 '21 at 20:42

1 Answers1

0

Figured it out...finally. At first, I figured out the reason it wasn't saving is because it was failing the formset.is_valid check, so I added an

        else:
            print(formset.errors)

to the views.py and found out that my error was

[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

What solved the issue, is in my for loop, I added {{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>