Django: How to create a model that contains a foreign key with CreateView?

If possible, I want to make a model that includes the foreign key with class-based CreateView. I know it can be done using a function.

models.py

class Pizza(models.Model):
    name = models.CharField(max_length=20)
    def __str__(self):
      return self.name
    def get_absolute_url(self):
      return "/pizzas"

class Topping(models.Model):
    pizza = models.ForeignKey(Pizza, on_delete=models.CASCADE)
    name = models.CharField(max_length=20)
    def __str__(self):
      return self.name
    def get_absolute_url(self):
       return reverse("pizza", kwargs={"pizza_id": self.pizza.pk})

views.py

class NewTopping(CreateView):
    model = Topping
    template_name = "pizzas/new_topping.html"
    form_class = ToppingForm

urls.py

path("topping/<pk>/create",views.NewTopping.as_view(),name="new_topping")

I've tried to do it like this, but I get an integrity error when I try to save the new instance:

NOT NULL constraint failed: pizzas_topping.pizza_id

From a logical point of view, I would suggest, that you change your models, because a pizza can contain several toppings and a topping can be on several pizzas. So I would suggest, that you add a ManyToManyField "toppings" to your Pizza model and delete the ForeignKeyField to the Pizza model in the Topping model (see code below). If you implement it with your models, you will maybe run into problems.

Each object in the Topping table is only connected with one Pizza object. So if you have for example tomato sauce as a Topping, you have to add multiple objects with the name 'tomato sauce', each connected to a different type of Pizza. If you have for example 'Pizza Margherita', 'Pizza Funghi' and 'Pizza Prosciutto' as Pizza instances, you should have three instances of 'tomato sauce' in your Topping table in the database, because each of the three Pizzas has tomato sauce on it.

Behind the scenes, Django creates an intermediary join table to represent the many-to-many relationship.

So, with a ManyToManyField, Django creates a table (which you don't see as a Model representation) which stores - in your case and with my suggestion - the ID of the Pizza and the ID of the Topping. For further explanation on ManyToManyFields, check the Django Documentation

#models.py
class Pizza(models.Model):
    name = models.CharField(max_length=20)
    toppings = models.ManyToManyField(Topping)
    ...

class Topping(models.Model):
    name = models.CharField(max_length=20)
    ...

To your question, you should provide the forms.py and maybe also your HTML template. Otherwise one cannot answer your question.

Back to Top