Django模型继承除IntegerField之外的所有超级模型字段

Django模型继承除IntegerField之外的所有超级模型字段,django,django-models,django-inheritance,Django,Django Models,Django Inheritance,我有一个奇怪的问题,我有一个模型的层次结构,一个抽象的用户类: 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.

我有一个奇怪的问题,我有一个模型的层次结构,一个抽象的用户类:

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
然后是继承自该类的person类和company类(此类没有问题):

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
如您所见,IntegerField()的唯一字段是age字段。 现在我有一个Traveler和一个Driver类,它们继承自person类, 问题是年龄字段,不会显示在数据库中,除非我在其中一个类中重写它,这就是我所做的,我在Traveler中重写它,所以它出现在数据库中,但没有在驱动程序中重写它,所以它没有显示。 旅客:

class Traveller(Person):
    photo = models.ImageField(null=True, upload_to='travellers/profile_pictures')
    age = models.IntegerField(null=True)

    class Meta:
        verbose_name_plural = 'Travellers'
司机:

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')

我需要知道如何解决这个问题,或者问题出在哪里,非常感谢您的帮助。

发生这种情况的原因是您的
age
字段与
age
函数同名。因此,Python会忽略
age=…
字段而使用
age
函数,因为这是您最后一次定义
age
变量

出于同样的原因,
age
字段会在子类中弹出:您在那里定义了一个
age
变量,该变量优先于“继承的”age方法

您应该重命名其中一个。例如:

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
类人员(用户):
性别=(‘F’、‘女性’、(‘M’、‘男性’))
name=models.CharField(最大长度=50,null=True)
姓氏=models.CharField(最大长度=50,null=True)
adress=models.CharField(最大长度=255,null=True)
出生日期=models.DateField(null=True)
gender=models.CharField(max_length=1,choices=gender,null=True)
_age=models.IntegerField(null=True)
年龄(自我):
今天=日期。今天()
bod=自我出生日期
月日之前=(今天.月,今天.日)<(董事会.月,董事会.日)
今天返回。年份-自我出生日期。年份-出生日期之前
类元:
抽象=真

请注意,
年龄
的计算并不完全准确:如果我们在那一年的生日之前,您需要从年龄中减去一个。

发生这种情况的原因是您的
年龄
字段与
年龄
函数同名。因此,Python会忽略
age=…
字段而使用
age
函数,因为这是您最后一次定义
age
变量

出于同样的原因,
age
字段会在子类中弹出:您在那里定义了一个
age
变量,该变量优先于“继承的”age方法

您应该重命名其中一个。例如:

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
类人员(用户):
性别=(‘F’、‘女性’、(‘M’、‘男性’))
name=models.CharField(最大长度=50,null=True)
姓氏=models.CharField(最大长度=50,null=True)
adress=models.CharField(最大长度=255,null=True)
出生日期=models.DateField(null=True)
gender=models.CharField(max_length=1,choices=gender,null=True)
_age=models.IntegerField(null=True)
年龄(自我):
今天=日期。今天()
bod=自我出生日期
月日之前=(今天.月,今天.日)<(董事会.月,董事会.日)
今天返回。年份-自我出生日期。年份-出生日期之前
类元:
抽象=真

请注意,
年龄的计算并不完全准确:如果我们在那一年的生日之前,您需要从年龄中减去一个。

您确实点了点头,在这里添加了一个
年龄
字段。由于您使用相同的名称定义了一个函数,因此该属性被“覆盖”。请重命名其中一个。请注意,年龄并不是出生年份和当前年份之间的差异。@WillemVanOnsem谢谢你,伙计,我修正了方法名称,解决了问题,但我不明白你所说的“年龄不是出生年份和当前年份之间的差异”。。。那么它是如何计算的呢?如果你有dob,为什么首先要将年龄存储在数据库中?切勿存储可从其他字段计算的属性。如果我是你,我会完全删除
age
字段,只保留
def age(self)
方法(将其更改为
@property
,甚至更好)以返回计算值。@dirkgoten:我想可能是因为一个人决定指定他/她的年龄,而不是他/她的出生日期。你没有在这里添加
age
字段。由于您使用相同的名称定义了一个函数,因此该属性被“覆盖”。请重命名其中一个。请注意,年龄并不是出生年份和当前年份之间的差异。@WillemVanOnsem谢谢你,伙计,我修正了方法名称,解决了问题,但我不明白你所说的“年龄不是出生年份和当前年份之间的差异”。。。那么它是如何计算的呢?如果你有dob,为什么首先要将年龄存储在数据库中?切勿存储可从其他字段计算的属性。如果我是你,我会完全删除
age
字段,只保留
def age(self)
方法(将其更改为
@property
,甚至更好)以返回计算值。@dirkgoten:我想是因为一个人可能决定指定他/她的年龄,而不是他/她的出生日期。