pythondjangodjango-inheritance

In Django - Model Inheritance - Does it allow you to override a parent model's attribute?


I'm looking to do this:

class Place(models.Model):
   name = models.CharField(max_length=20)
   rating = models.DecimalField()

class LongNamedRestaurant(Place):  # Subclassing `Place`.
   name = models.CharField(max_length=255)  # Notice, I'm overriding `Place.name` to give it a longer length.
   food_type = models.CharField(max_length=25)

This is the version I would like to use (although I'm open to any suggestion): http://docs.djangoproject.com/en/dev/topics/db/models/#id7

Is this supported in Django? If not, is there a way to achieve similar results?


Solution

  • Updated answer: as people noted in comments, the original answer wasn't properly answering the question. Indeed, only the LongNamedRestaurant model was created in database, Place was not.

    A solution is to create an abstract model representing a "Place", eg. AbstractPlace, and inherit from it:

    class AbstractPlace(models.Model):
        name = models.CharField(max_length=20)
        rating = models.DecimalField()
    
        class Meta:
            abstract = True
    
    class Place(AbstractPlace):
        pass
    
    class LongNamedRestaurant(AbstractPlace):
        name = models.CharField(max_length=255)
        food_type = models.CharField(max_length=25)
    

    Please also read @Mark answer, he gives a great explanation why you can't change attributes inherited from a non-abstract class.

    (Note this is only possible since Django 1.10: before Django 1.10, modifying an attribute inherited from an abstract class wasn't possible.)

    Original answer

    Since Django 1.10 it's possible! You just have to do what you asked for:

    class Place(models.Model):
        name = models.CharField(max_length=20)
        rating = models.DecimalField()
    
        class Meta:
            abstract = True
    
    class LongNamedRestaurant(Place):  # Subclassing `Place`.
        name = models.CharField(max_length=255)  # Notice, I'm overriding `Place.name` to give it a longer length.
        food_type = models.CharField(max_length=25)