Django ORM Inheritance: You are trying to add a non-nullable field 'dish_ptr' to [...] without a default

Viewed 1186

I am working on a restaurant app (and new to Django/Python). I want to have a parent class Dish that will contain some counter or ID that increments for every instance of a child class of Dish. The instances are dishes like Pizza, Pasta, etc with different characteristics and relations. I'm trying to make Dish concrete, because in that case I reckon I just access Dish's PK and that will give each menu-item a Dish-ID. However, I don't know how to correctly fix the errors I come across: You are trying to add a non-nullable field 'pasta_ptr'.

Here are the relevant code snippets:

class Dish(models.Model):
  pass # should automatically generate PK, right?

class Pasta(Dish):
  name = models.CharField(max_length=64, primary_key=True)
  price = models.DecimalField(max_digits=6, decimal_places=2)

  def __str__(self):
    return f"{self.name}, price: ${self.price}"

class Pizza(Dish):
  sizestyle = models.CharField(max_length=4, choices=SIZESTYLE_CHOICES, default=SMALL_REGULAR)
  topping_count = models.IntegerField(default=0, validators=[MaxValueValidator(5), MinValueValidator(0)])
  price = models.DecimalField(max_digits=6, decimal_places=2)

  def __str__(self):
    return f"Price for {self.sizestyle} pizza with {self.topping_count} toppings: ${self.price}"

class Sub(Dish):
  name = models.CharField(max_length=64, primary_key=True)
  price_category = models.ForeignKey(SubPrice, on_delete=models.DO_NOTHING, related_name="sub_price_category")

  def __str__(self):
    return f"{self.name}, Price Category: {self.price_category}"

class Platter(Dish):
  name = models.CharField(max_length=64, primary_key=True)
  price_large = models.DecimalField(max_digits=6, decimal_places=2, default=0)
  price_small = models.DecimalField(max_digits=6, decimal_places=2, default=0)

  def __str__(self):
    return f"{self.name} price: Large ${self.price_large}, Small ${self.price_small}"
1 Answers

If you wanted to inherit from Dish() but not have it in the database, you could do this: Django abstract base class docs

class Dish(models.Model):
    # your model structure

    class Meta:
        abstract = True

class Pizza(Dish):
    # your model structure

This would just inherit whatever is in Dish when you use it. You will not see Dish as a table in the database.

If you do want to use it as a parent class, you need to tell the subclasses that Dish is a parent class: django many to one docs

class Dish(models.Model):
    pass

class Pizza(models.Model):
    dish = models.ForeignKey(Dish, on_delete=models.CASCADE)
    # other model structure

This would create an id for Dish in the database and when Pizza is created, it would reference the id (pk) of Dish.

Related