Django model queryset using related names and managers

1.5k Views Asked by At

I have 4 models -

class Group(models.model):
    group_id = models.CharField(max_length=10)
    name = models.CharField(max_length=20)

class User(models.model):
    user_id = models.CharField(max_length=10)
    grp = models.ForeignKey(Group, null=True, blank=True)
    user_name = models.CharField(max_length=50)
    contact_no = models.CharField(max_length=20)

class DesigType(models.model):
    desig_name = models.CharField(max_length=10)

class Designation(models.model):
    user = models.ForeignKey(User, null=True, blank=True, related_name='desigs')
    desig_type = models.ForeignKey(DesigType, null=True, blank=True, related_name='desigs')

Group model holds groups of users. User holds records for each individual user. DesigType has information about "type of designation", like maybe manager, team lead etc. Designation stores the exact designation - for example, for manager DesigType, Designation might have project manager or account manager; similarly, for team lead DesigType, Designation might have front-end lead or back-end lead.

The UI currently shows a list of users under a group. I want to implement a search functionality according to desig_name. The UI sends me the group_id and the text entered by the end-user in the search box, and I have to return only those Users which have the corresponding desig_name.

I have already done the above, by using a property to return a list of desig_names that a User has and checking whether the user input exists in the list.

This is a property under User -

@cached_property
def desig_types(self):
    desig_types = []
    for value in self.desigs.select_related('desig_type').values('desig_type__desig_name'):
        desig_types.append(value['desig_type__desig_name'])
    return desig_types

In my view I have a generic search function which takes any user filter to return the appropriate list of users.

group = Groups.objects.get(pk=grp_id)
_queryset = group.user_set.filter(**user_filter)

The above code works for filtering according to contact_no and user_name. For contact_no, **user_filter is group.user_set.filter(contact_no=user_input), and for user_name, it's group.user_set.filter(user_name=user_input). I want it to also work for filtering according to desig_name, but I couldn't figure out how to navigate through the relationships so I wrote the code below, that retrieves a list of user_ids which have the user inputted desig_name.

required_users = []
for user in group.user_set.all():
        user_desig_names = user.desig_types
        if user_input in user_desig_names:
            required_users.append(user.user_id)
return required_users

I then pass in the filter as group.user_set.filter(user_id__in=required_users). But as you see, I have to have an additional code to get the user_ids, instead of directly using **user_filter, like with user_name or contact_no.

Does anyone know how I can do that?

0

There are 0 best solutions below