Dylan Klomparens
Dylan Klomparens

Reputation: 2932

Django 1.7 migrations with abstract base classes

I am trying to upgrade to Django 1.7 and switch from South to Django's integrated migration. I ran into a problem with my models. I have a base class:

class CalendarDisplay():
    """
    Inherit from this class to express that a class type is able to be displayed in the calendar.
    Calling get_visual_end() will artificially lengthen the end time so the event is large enough to
    be visible and clickable.
    """

    start = None
    end = None

    def __init__(self):
        pass

    def get_visual_end(self):
        if self.end is None:
            return max(self.start + timedelta(minutes=15), timezone.now())
        else:
            return max(self.start + timedelta(minutes=15), self.end)

    class Meta:
        abstract = True

And here is an example of a class that inherits it:

class Reservation(models.Model, CalendarDisplay):
    user = models.ForeignKey(User)
    start = models.DateTimeField('start')
    end = models.DateTimeField('end')
    ...

Now I try to migrate my app, but get the error below: python manage.py makemigrations

Migrations for 'Example':
  0001_initial.py:
    - Create model Account
    ...
    ValueError: Cannot serialize: <class Example.models.CalendarDisplay at 0x2f01ce8>
    There are some values Django cannot serialize into migration files.

What are my options for resolving this? Can Django 1.7 migrations handle abstract base classes? I would prefer to keep my abstract base class and inherit it, however, copying and pasting the necessary functions into the appropriate classes is a last resort.

Upvotes: 1

Views: 1213

Answers (1)

dgel
dgel

Reputation: 16806

Your abstract base class should extend models.Model:

class CalendarDisplay(models.Model):
    ...

Your child class should then only extend CalendarDisplay- it doesn't need to extend models.Model:

class Reservation(CalendarDisplay):
    ...

Also, you need to either not override __init__ in CalendarDisplay or you need to call super in your init:

def __init__(self, *args, **kwargs):
    super(CalendarDisplay, self).__init__(*args, **kwargs)

Upvotes: 2

Related Questions