7

I have inheritance between Employee and Manager classes. Employee - superclass, Manager - subclass.

class Employee(models.Model):
    name = models.CharField(max_length=50, null=False)
    address = models.CharField(max_length=50, null=False)
    
class Manager(Employee):
    department = models.CharField(max_length=50)
    """
    Here I don't want the 'name' and 'address' fields of Employee class.
    (I want other fields of Employee and 'department' field of this 
    class to be stored in Manager table in database)
    """

How can achieve this. Thanks in advance.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Kholdarbekov
  • 973
  • 1
  • 10
  • 28

3 Answers3

14

You can make private variables in python class using 2 underscores (__), check this example for more.

However they will store that values in child object as there is no such thing as private or protected in Python.

But another approach can work for Django. In Django model fields are stored depending on their value (CharField, DateField and etc.) but if you will make item value None or any other static value (ex. "string"), that should solve your problem:

class Manager(Employee):
  name = None
  address = None
  # other_stuffs.

In that example, Manager should not have name and address columns in database and when you will try to access them, you will get None. And if you want to get AttributeError (Django raises that when object hasn't requested key) then you can also add property:

class Manager(Employee):
  name = None
  @property
  def name(self):
    raise AttributeError("'Manager' object has no attribute 'name'")
Community
  • 1
  • 1
Emin Mastizada
  • 1,375
  • 2
  • 15
  • 30
10

I'd use 3 classes:

class BaseEmployee(models.Model):
    # All your common fields

class Employee(BaseEmployee):
    name = models.CharField(max_length=50, null=False)
    address = models.CharField(max_length=50, null=False)

class Manager(BaseEmployee):
    department = models.CharField(max_length=50)

I think that achieves what you wanted.

foz
  • 3,121
  • 1
  • 27
  • 21
  • the accepted answer is not working in my case on Django 3.2 and this is a much OOP way to achieve this thank u! – Fathy Oct 17 '22 at 11:44
1

You need to use 3 classes AbstractEmployee with abstract = True, Employee and Manager as shown below. abstract = True makes AbstractEmployee class an abstract class so a table is not created from AbstractEmployee class while each table is created from Employee and Manager classes and to remove the inherited fields name and address from Manager class, set None to them:

class AbstractEmployee(models.Model):
    name = models.CharField(max_length=50, null=False)
    address = models.CharField(max_length=50, null=False)

    class Meta:
        abstract = True # Here
    
class Employee(AbstractEmployee):
    pass
        
class Manager(AbstractEmployee):
    name = None # Here
    address = None # Here
    department = models.CharField(max_length=50)
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129