John
John

Reputation: 2922

Can I use ABC and Django Abstract classes together in Python?

I have a django abstract class:

class AbstractModel(models.Model):
    date_added = models.DateField(auto_now_add=True)

    class Meta:
        abstract = True

I want my concrete classes (Django Models) to subclass this abstract class, but I also want to make sure that all my concrete classes always implement very specific methods using abc.

I tried doing this:

class AbstractBaseClass(AbstractModel, metaclass=abc.ABCMeta):
    @abstractmethod
    def important_method(self):
        pass

class MyDjangoModel(AbstractBaseClass):
    ...

And I tried:

class AbstractBaseClass(ABC):
    @abstractmethod
    def important_method(self):
        pass

class MyDjangoModel(AbstractModel, AbstractBaseClass):

Neither worked. They both say:

TypeError: metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases

Is there a way to do this, or is this impossible?

Upvotes: 3

Views: 598

Answers (1)

funnydman
funnydman

Reputation: 11346

You're pretty close to the right solution, see the example:

import abc

from django.db import models


class AbstractModelMeta(abc.ABCMeta, type(models.Model)):
    """AbstractModelMeta used as a metaclass"""


class AbstractBaseClass(models.Model, metaclass=AbstractModelMeta):
    date_added = models.DateField(auto_now_add=True)

    class Meta:
        abstract = True

    @abc.abstractmethod
    def important_method(self):
        pass


class MyDjangoModel(AbstractBaseClass):
    first_name = models.CharField(max_length=10)

You'll get an error if abstract methods aren't implemented as expected:

>>> from main.models import MyDjangoModel
>>> m = MyDjangoModel()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
TypeError: Can't instantiate abstract class MyDjangoModel with abstract methods important_method

Upvotes: 5

Related Questions