在Django中考虑这个Family
模型:
class Family(models.Model):
EMPLOYEE = 'Employee'
PARTNER = 'Partner'
BIRTH_PARENT_CHOICES = (
(EMPLOYEE, EMPLOYEE),
(PARTNER, PARTNER),
)
employee_user = models.OneToOneField(User, blank=True, null=True, related_name='employee_family')
partner_user = models.OneToOneField(User, blank=True, null=True, related_name='partner_family')
employee_first_name = models.CharField(max_length=255, blank=True)
employee_last_name = models.CharField(max_length=255, blank=True)
employee_email = models.CharField(max_length=255, blank=True)
employee_phone = models.CharField(max_length=255, blank=True)
partner_first_name = models.CharField(max_length=255, blank=True)
partner_last_name = models.CharField(max_length=255, blank=True)
partner_email = models.CharField(max_length=255, blank=True)
partner_phone = models.CharField(max_length=255, blank=True)
point_of_contact = models.CharField(max_length=255, choices=BIRTH_PARENT_CHOICES)
Family
由员工和合作伙伴组成,两者都具有各种属性(用户,名字,姓氏,电子邮件,电话)。还有一个point_of_contact
字段,可以是'Employee'
或'Partner'
。
我希望能够在family
的实例Family
上执行类似
family.point_of_contact.phone_number
除非family.employee_phone_number
和family.point_of_contact == Family.EMPLOYEE
,否则将解析为family.partner_phone_number
,对于first_name
,last_name
等同样会解析为<{1}}
然而,据https://docs.djangoproject.com/en/2.0/ref/models/fields/我所知,在Django字段上定义其他属性是不可能的。还有其他方法可以做到这一点吗?
答案 0 :(得分:1)
不,为了做到这一点,您需要创建一个单独的模型Contact
并使用Family
从OneToOneField
加入,如果每个家庭只能有一个联系人,如果每个家庭可以有多个联系人,则使用ForeignKey
模型中的Contact
。
答案 1 :(得分:1)
Django没有提供这样做的方法,但你可以用一些简单的Python来做到这一点:
from types import SimpleNamespace
class Family(SimpleNamespace):
EMPLOYEE = 'employee'
PARTNER = 'partner'
@property
def contact(self):
return SimpleNamespace(**{
attr: getattr(self, '%s_%s' % (self.point_of_contact, attr))
for attr in 'first_name last_name'.split()
})
family = Family(
employee_first_name='Kurt',
employee_last_name='Peek',
partner_first_name='Jane',
partner_last_name='Doe',
point_of_contact=Family.EMPLOYEE,
)
print(family.contact.first_name)
print(family.contact.last_name)
此处SimpleNamespace
以两种方式使用:
Family
的超类使这个例子易于测试 - 跳过它并坚持models.Model
。contact
属性中,请保留该内容。