2

I thought I would up my python game with Django a bit by developing a large scale business app for fun. I seen the need for a common ancestor approach to model inheritence and tried to implement it based on the official documentation. However, I keep getting this very annoying Message which I'm not sure what to do with.

  • Dj Version: Django 1.7
  • Py Version: Python 3.4.2

Message

$ python manage.py makemigrations
You are trying to add a non-nullable field 'businessentity_ptr' to business without a default; we can't do that (the database needs something to populate existing rows).

Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows)
 2) Quit, and let me add a default in models.py

Models.py

class BusinessEntity(models.Model):
    title = models.CharField(max_length=180)

    def __str__(self):
        return self.title


class Business(BusinessEntity):
    description = models.TextField(max_length=600)
    claimed = models.BooleanField(default=False)
    slug = models.SlugField()
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    updated = models.DateTimeField(auto_now_add=False, auto_now=True)

    def __str__(self):
        return self.description

What I've Tried, (which everyone will hate):

  1. Deleting the DB & Re-migrating
  2. setting a default value for all fields
  3. Setting all fields to null = True

I have seen a hack around for this but I don't think it's a good approach. Maybe there is someone out there who understand Django Common Ancestors much better and point me in the right direction.

ham-sandwich
  • 3,975
  • 10
  • 34
  • 46
  • 1
    Do you need BusinessEntity to be an actual concrete model that you can query? Otherwise it would be better as an abstract model, and your problem wouldn't happen. – Daniel Roseman Nov 06 '14 at 13:04
  • 1
    Django inheritance for models can get messy (even with mixins instead of concrete ancestors). I regret having used it in my current project. I found a lot of corner cases the [POLA](http://en.wikipedia.org/wiki/Principle_of_least_astonishment) is violated. – Paulo Scardine Nov 06 '14 at 13:05
  • @DanielRoseman yeah, it's just abstract. There is no need to query over the BusinessEntity object. – ham-sandwich Nov 06 '14 at 13:10

1 Answers1

10

Since your parent model is intended to be abstract, you should mark it as such.

class BusinessEntity(models.Model):
    title = models.CharField(max_length=180)

    class Meta:
        abstract = True

This prevents Django from creating a separate table for it, and therefore needing a _ptr field to point back to it from the subclass. Instead, the table for your subclass will be created to include the inherited field(s) directly.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895