How to use list of values in get method?

Viewed 51

I have a template filter in Django that looks ugly and not very pythonic. Is there a way to combine all the get requests into a list?

@register.filter(name='is_supervisor')
def is_in_group(user):
    group = Group.objects.get(name="security supervisor")
    group1 = Group.objects.get(name="cage supervisor")
    group2 = Group.objects.get(name="casino supervisor")
    group3 = Group.objects.get(name="food bev supervisor")
    return True if group or group1 or group2 or group3 in user.groups.all() else False

I tried using a Q filter for chaining them together but that did not work. I have also tried:

@register.filter(name='is_supervisor')
def is_in_group(user):
    types = ["security supervisor", "cage supervisor",
             "casino supervisor", "food bev supervisor"]
    for name in types:
        test1 = Group.objects.get(name=name)
    return True if test1 in user.groups.all() else False
2 Answers

The reason this does not workis because your group or group1 or group2 or group3 in user.groups.all() is parsed as (group) or (group1) or (group2) or (group3 in user.groups.all()), and thus it will evaluate the truthiness of the group object. Normally these objects have by default truthiness True, and therefore the condition will always succeed.

We however do not need to use all those queries, we can check this with a single query. Indeed:

@register.filter(name='is_supervisor')
def is_in_group(user):
    return Group.objects.filter(
        user=user,
        name__in=[
            'security supervisor',
            'cage supervisor',
            'casino supervisor',
            'food bev supervisor'
        ]
    ).exists()

I believe that group_names_list must exist and it would be outside of the function (at least this way the name of function makes sense). So you can implement the function like this:

@register.filter(name='is_supervisor')
def is_in_groups(user, group_names_list):
    result = False
    for group_name in group_names_list:
        result = result or Group.objects.get(name=group_name) in user.groups.all()
    return result

and pass the group_names_list to the function:

group_names_list = ['security supervisor', 'cage supervisor', 'casino supervisor', 'food bev supervisor']

EDIT: Thanks to @Willem Van Onsem, we can implement this function as:

@register.filter(name='is_supervisor')
def is_in_groups(user, group_names_list):
    return Group.objects.filter(user=user, name__in=group_names_list)

Which I think must be more efficient.

Related