David R.
David R.

Reputation: 935

Constructing Q objects dynamically, or NOP

I am trying to construct filter dynamically based on passed query parameters. Code below. Because the filter might end up empty, in which case all objects need to be returned, this is coming out very ugly.

Is there a way to do this cleanly? Maybe if there is a default Q that means 'do not nothing'?

def get(self, request, *args, **kwargs):
    q = None
    for field, value in request.GET.items():
        if field not in Project._meta.fields:
            continue
        if q is None:
            q = Q(**{'{}'.format(field): value})
        else:
            q &= Q(**{'{}'.format(field): value})

    if q is None:
        projects = get_objects_for_user(request.user, ['api.view_project', 'api.edit_project', 'api.owner_project'], any_perm=True)
    else:
        projects = get_objects_for_user(request.user, ['api.view_project', 'api.edit_project', 'api.owner_project'], any_perm=True).filter(q)

    ser = ProjectSerializer(projects, many=True)

    return Response(ser.data, status=status.HTTP_200_OK)

Upvotes: 0

Views: 46

Answers (2)

I recommend to use django-filter:

Example of filter class:

import django_filters

class ProjectFilter(django_filters.FilterSet):

    class Meta:
        model = Product
        fields = [
            'id',
            'name',
            'user',
            'user__username',
        ]

Example of view function:

def get(self, request, *args, **kwargs):
    projects = get_objects_for_user(request.user, ['api.view_project', 'api.edit_project', 'api.owner_project'], any_perm=True)

    projects = ProjectFilter(request.GET, queryset=projects)

    ser = ProjectSerializer(projects, many=True)

    return Response(ser.data, status=status.HTTP_200_OK)

Upvotes: 0

AKX
AKX

Reputation: 169318

Just Q() should filter out nothing at all.

Upvotes: 1

Related Questions