Reputation: 57641
Consider this Family
model in Django:
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)
A Family
consists of an employee and a partner, both of which have various attributes (user, first name, last name, email, phone). There is also a point_of_contact
field which is either 'Employee'
or 'Partner'
.
What I'd like to be able to do is to, on an instance family
of Family
, do something like
family.point_of_contact.phone_number
which would resolve to family.employee_phone_number
if family.point_of_contact == Family.EMPLOYEE
and family.partner_phone_number
otherwise, and similarly for first_name
, last_name
, etc.
As far as I can tell from https://docs.djangoproject.com/en/2.0/ref/models/fields/, however, it isn't possible to define additional attributes on Django fields. Is there some other way I could do this?
Upvotes: 2
Views: 227
Reputation: 36043
Django doesn't provide a way to do this, but you can do it with some simple 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)
Here SimpleNamespace
is used in two ways:
Family
to make this example easy to test - skip that and stick to models.Model
.contact
property, keep that.Upvotes: 1
Reputation: 5867
No, in order to do that, you would need to create a separate model Contact
and join to it from Family
using a OneToOneField
if there can only be one contact per family, or using a ForeignKey
in your Contact
model if there can be more than one contact per family.
Upvotes: 1