How to submit create view with ManytoMany model?

o I am trying to do a CreateView class which saves recipe entered by user, however instead of using a textfield, I am trying to capture each measurement of each ingredient.

My models: I am not sure if the problem lies here

class IngredientList(models.Model):
    ...

class Recipe(models.Model):
    cuis = [
        ('Italian', 'It'),
        ('French', 'Fr'),
    ]
    title = models.CharField(max_length=100)
    ingredients = models.ManyToManyField(
        IngredientList, through='ShoppingList')
    instructions = models.TextField(max_length=3000)
    serving_size = models.IntegerField(default=0)
    cuisine_type = models.CharField(
        max_length=100, choices=cuis, blank=True, null=True)
    image = models.ImageField(default='recipe.jpg', blank=True, null=True)
    duration = models.IntegerField(blank=True, default=0)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('recipe-detail', kwargs={'pk': self.pk})


class RecipeList(models.Model):
    recipe = models.ForeignKey(Recipe, on_delete=models.CASCADE)
    ingredients = models.ForeignKey(IngredientList, on_delete=models.CASCADE)
    measurement = models.FloatField(default=1)

    def __str__(self):
        return self.recipe.title

My form:

class RecipeForm(forms.Form):
    name = forms.CharField()
    ingredient = forms.ModelMultipleChoiceField(
        IngredientList.objects.all(),  widget=forms.CheckboxSelectMultiple)
    measurement = forms.IntegerField()
    instructions = forms.CharField(widget=forms.Textarea)
    serving_size = forms.IntegerField()
    cuisine_type = forms.ChoiceField(choices=RecipeList.cuis)
    duration = forms.IntegerField()

And the views :

class RecipeCreateView(FormView):
    template_name = "recipe/recipeList_form.html"
    form_class = RecipeForm
    success_url = reverse_lazy('recipes')

    def form_valid(self, form):
        self.name = form.cleaned_data['name']
        self.ingredient = form.cleaned_data['ingredient']
        self.measurement = form.cleaned_data['measurement']
        self.instructions = form.cleaned_data['instructions']
        self.serving_size = form.cleaned_data['serving_size']
        self.cuisine_type = form.cleaned_data['cuisine_type']
        self.duration = form.cleaned_data['duration']

        recipe = Recipe(name=self.name, instructions=self.instructions, serving_size=self.serving_size,
                            cuisine=self.cuisine_type, duration=self.duration)
        recipe.save()
        ingredient_list = IngredientList.objects.filter(pk__in=self.ingredient)
        for i in ingredient_list:
            recipe.ingredients.add(i)
        return super(RecipeCreateView, self).form_valid(form)

The problem is, I am not able to state the measurement of each ingredient. The ingredients are being captured and outputted to the screen within its parent recipe.

You have ingredients defined as a ManyToMany through ShoppingList, but your class is named RecipeList. If they’re not supposed to be the same “thing”, please explain a little more as to what each of those models are supposed to represent.

Also, you’re doing a lot more work than necessary working these forms.

In general, you’ll want to use your form for Recipe, and an Inline formset for your ingredients. Each form in the formset will have the ingredient and quantity (measurement) to be stored as the individual rows in your through table.

I suggest you review:

Also, for a better look at how the Generic Class-Based views work, look at both:

Understanding how the GCBVs work will help you see what you should override and when.