gozzilli
gozzilli

Reputation: 8337

Subclassing django model doesn't carry the Manager

If I have a Django model:

class Person(models.Model):
    name = models.CharField(max_length=45)
    surname = models.CharField(max_length=45)
    objects = PersonManager()

and its manager:

class PersonManager(models.Manager):

    def create_person(self, fullname):

        name, surname = fullname.split(" ", 1)
        return self.create(name=name, surname=surname)

Extending that class:

class Actor(Person):
    pass

doesn't have the same manager object, but the default one.

In [5]: Person.objects.create_person
Out[5]: <bound method PersonManager.create_person of <xxx.PersonManager object at 0x10297d190>>

In [6]: Actor.objects.create_person
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-6-468f84e48664> in <module>()
----> 1 Actor.objects.create_person

AttributeError: 'Manager' object has no attribute 'create_person'

Why is that and how can I propagate the manager to all subclasses?

Upvotes: 0

Views: 158

Answers (1)

Daniel Karlsson
Daniel Karlsson

Reputation: 136

You can read more about this here: https://docs.djangoproject.com/en/dev/topics/db/managers/#custom-managers-and-model-inheritance

Basically managers are not inherited (from ordinary models). To get around this you can manually declare the manager in each model that should use the PersonManager. Or you can make Person an abstract model, that way all subclasses will inherit the PersonManager. Considering that you might want to add Directors, Producers or Technicians this might be the way to go. To do that you add the abstract attribute to Persons metaclass.

class Person(models.Model):
    name = models.CharField(max_length=45)
    surname = models.CharField(max_length=45)
    objects = PersonManager()

    class Meta:
        abstract = True

Upvotes: 1

Related Questions