将其他属性添加到Django字段

时间:2018-03-21 17:48:50

标签: python django

在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_numberfamily.point_of_contact == Family.EMPLOYEE,否则将解析为family.partner_phone_number,对于first_namelast_name等同样会解析为<{1}}

然而,据https://docs.djangoproject.com/en/2.0/ref/models/fields/我所知,在Django字段上定义其他属性是不可能的。还有其他方法可以做到这一点吗?

2 个答案:

答案 0 :(得分:1)

不,为了做到这一点,您需要创建一个单独的模型Contact并使用FamilyOneToOneField加入,如果每个家庭只能有一个联系人,如果每个家庭可以有多个联系人,则使用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以两种方式使用:

  1. 作为Family的超类使这个例子易于测试 - 跳过它并坚持models.Model
  2. contact属性中,请保留该内容。