2

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?

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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:

  1. As a superclass of Family to make this example easy to test - skip that and stick to models.Model.
  2. In the contact property, keep that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.