Question

I've two Django models:

class Person(CommonModel):
    """ Person """
    person_type = models.ForeignKey(PersonType)
    ciam_id = models.PositiveIntegerField()  # ForeignKey('ciam.person_id')
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    middle_name = models.CharField(max_length=50)
    empl_id = models.CharField(max_length=8)
    pcn = models.CharField(max_length=50)
    ...

and

class PositionHierarchy(CommonModel):
    """ Position Hierarchy  """
    pcn = models.CharField(max_length=50)
    title = models.CharField(max_length=100)
    level = models.CharField(max_length=25)
    reports_to_pcn = models.CharField(max_length=50, db_index=True)  # FK?

Unfortunately, for reasons beyond my control (and beyond reason), the only way to tell if a person is a manager or not is to look at Person.pcn, use that look up their PositionHierarchy by pcn, and then look at their level in PositionHierarchy. Similarly, the only way to find out their manager's name (which I need a lot) is to use their Person.pcn, look up their PositionHierarchy by pcn, look up their manager's PositionHierarchy by reports_to_pcn, then use that pcn to look up the manager's Person record. And none of these PCNs are allowed to be replaced by a Foreign Key to the PositionHeirarchy model. What a convoluted mess, right?

So I need to be able to quickly look up a person, and see their level and manager name.

Was it helpful?

Solution

The solution is a custom manager based on this blog post:

class PersonWithManagerManager(CommonManager):
    """ Manager to get a query that adds the level and manager name
    to the person record """
    def get_query_set(self):
        qs = super(PersonWithManagerManager, self).get_query_set()
        cp_tab = qs.query.get_initial_alias()
        # Join to the PCN table to find the position
        pcn_tab = qs.query.join(
            (
                cp_tab,
                PositionHierarchy._meta.db_table,
                'pcn',
                'pcn'
            ), promote=True)
        # Find the manager's PCN
        man_pcn_tab = qs.query.join(
            (
                pcn_tab,
                PositionHierarchy._meta.db_table,
                'reports_to_pcn',
                'pcn'
            ), promote=True)
        # Find the manager's person record
        man_per_tab = qs.query.join(
            (
                man_pcn_tab,
                'cart_person',
                'pcn',
                'pcn'
            ), promote=True)
        return qs.extra(
            select={
                'level': '%s.level' % pcn_tab,
                'manager_last_name': '%s.last_name' % man_per_tab,
                'manager_first_name': '%s.first_name' % man_per_tab,
            }
        )

Now I can do print Person.extra_objects.filter(last_name='Tomblin').manager_last_name and get my manager's last name. One thing I can't do yet is filter on them.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top