5

Using multi-table inheritance, I have two models:

class Bird(models.Model):
    color = models.CharField()

class Bluebird(Bird):
    ...

Using these models, I can do this:

birds = Bird.objects.all()
for bird in birds:
    print bird.color

This is super simple, but I don't like allowing people to define arbitrary color values in some cases. For example, I want to prevent users from creating Bluebird objects for which the color field is set to anything but "blue" or, in more rare cases, "grey" or "brown". In other words, I want to set the choices kwarg on the inherited color field from within the Bluebird model. From a cursory internet search, it seems that Django doesn't currently allow model subclasses to override the fields from a parent.

How does one retain access to the color field in the parent class while defining acceptable choices in the child?

EDIT: This question focuses on Django < 1.8. In 1.8, the ability to pass a callable for a field's choices kwarg was added, and while that would be nice, I'm dealing with a system that hasn't yet been upgraded and upgrading is not currently an option.

user3934630
  • 281
  • 2
  • 9
  • A simple approach might be to leave `color` alone and just do it via validation. (That is, the user can choose something other than `blue`, but the validation will reject it as an invalid choice.) – Kevin Christopher Henry May 20 '15 at 23:10
  • 1
    While that would keep the data valid, the user experience would suffer as a result. In the worst-case scenario (i.e., they haven't the foggiest idea what colors a certain kind of bird can be), they would be reduced to guessing unless the valid options are presented to them by the form. Presenting options by overriding the ModelForm field is currently how I'm approaching this problem. – user3934630 May 21 '15 at 01:24

1 Answers1

-1

Use a property.

You can define the color value for each model and then return that as a property, if the color will be fixed, you don't need it in the database.

class Bird(models.Model):
   COLOR = None

   @property
   def color(self):
       return self.COLOR

class BlueBird(Bird):
   COLOR = 'Blue'

>>> b = BlueBird()
>>> b.color
'Blue'
Raydel Miranda
  • 13,825
  • 3
  • 38
  • 60