I'm having a weird issue, I have a models' hierarchy, an abstract User class:
class User(AbstractBaseUser):
user_name = models.CharField(max_length=32, unique=True)
email = models.EmailField(max_length=255, unique=True, null=True)
phone = PhoneNumberField()
access_token = models.CharField(max_length=255, unique=True, null=True)
notifications_token = models.CharField(max_length=255, unique=True, null=True)
photo = models.ImageField(null=True)
person_in_contact = models.CharField(max_length=32, null=True)
active = models.BooleanField(default=False)
confirmedEmail = models.BooleanField(default=False)
confirmedPhone = models.BooleanField(default=False)
completedProfile = models.BooleanField(default=False)
visible = models.BooleanField(default=True)
@property
def is_active(self):
return self.active
# def __str__(self):
# return "Client : " + self.user_name + " Email:" + self.email
def get_email(self):
return self.email
USERNAME_FIELD = 'user_name'
REQUIRED_FIELDS = ['user_name', 'phone', 'password']
class Meta:
abstract = True
then a person class and a company (no issue with this one) class that inherit from this one:
class Person(User):
GENDER = (('F', 'FEMALE'), ('M', 'MALE'))
name = models.CharField(max_length=50, null=True)
surname = models.CharField(max_length=50, null=True)
adress = models.CharField(max_length=255, null=True)
birth_date = models.DateField(null=True)
gender = models.CharField(max_length=1, choices=GENDER, null=True)
age = models.IntegerField(null=True)
def age(self):
today = date.today()
return today.year - self.birth_date.year
# def __str__(self):
# return super().__str__() + " Name : " + self.name
class Meta:
abstract = True
as you can see, the only field that's IntegerField() is the age field. now i have a Traveller and a Driver classes that inherit from the person class, the issue is the age field, doesn't show in the database, unless i override it in one of the classes, that's what i did, i override it in traveller so it appeared in the database, but didn't override it in the driver, so it didn't show. Traveller:
class Traveller(Person):
photo = models.ImageField(null=True, upload_to='travellers/profile_pictures')
age = models.IntegerField(null=True)
class Meta:
verbose_name_plural = 'Travellers'
Driver:
class Driver(Person):
rating = models.DecimalField(default=0, decimal_places=1, max_digits=3)
driving_license = models.CharField(max_length=50, null=True)
insurance_number = models.CharField(max_length=50, null=True)
company = models.ForeignKey(TransportCompany, on_delete=models.DO_NOTHING, null=True)
photo = models.ImageField(null=True, upload_to='drivers/profile_pictures')
i need to know how i can fix this, or what's the issue, any help is appreciated.
The reason this happens is because your age
field has the same name as the age
function. As a result, the age = ...
field is ignored by Python in favor of the age
function, since that is the last time you defined the age
variable.
For the same reason the age
field pops up in sublasses: you defined an age
variable over there, and that takes precedence over the "inherited" age method.
You should rename one of the two. For example with:
class Person(User):
GENDER = (('F', 'FEMALE'), ('M', 'MALE'))
name = models.CharField(max_length=50, null=True)
surname = models.CharField(max_length=50, null=True)
adress = models.CharField(max_length=255, null=True)
birth_date = models.DateField(null=True)
gender = models.CharField(max_length=1, choices=GENDER, null=True)
_age = models.IntegerField(null=True)
def age(self):
today = date.today()
bod = self.birth_date
before_dob = (today.month, today.day) < (bod.month, bod.day)
return today.year - self.birth_date.year - before_dob
class Meta:
abstract = True
Note that the calculation of the age
was not completely accurate: if we are before the birthday of that year, you need to subtract one from the age.