简体   繁体   中英

How to filter the query_set by multi-params?

How to filter the query_set by multi-params?

class UserListAPIView(ListAPIView):
    """
    return the user list
    """

    pagination_class = UserPageNumberPagination

    class Meta:
       ordering = ['-id']

    def get_serializer_class(self):
        return UserListSerializer

    def get_queryset(self):

        username = self.request.query_params.get("username")
        real_name = self.request.query_params.get("real_name")
        phone = self.request.query_params.get("phone")
        company_name = self.request.query_params.get("company_name")

        return User.objects.filter(
            is_admin=False,
            is_staff=False,
            is_superuser=False,

            username=username,
            real_name=real_name,
            phone=phone,
            company_name=company_name
            )  # if `username, real_name, phone, company_name` all are None, there gets `[]`

The serializer:

class UserListSerializer(ModelSerializer):
    """
    user list serializer
    """
    username = serializers.CharField(allow_null=True, allow_blank=True)
    real_name = serializers.CharField(allow_null=True, allow_blank=True)
    phone = serializers.CharField(allow_null=True, allow_blank=True)
    company_name = serializers.CharField(allow_null=True, allow_blank=True)

You see, my username , real_name, phone, company_name all are allow_null .

I want to query all the user that meet the conditions.

But gets [] , when I do not pass the username, real_name, phone, company_name .

I want to if the username is None, it do not filter the username , if real_name is None, it do not filter the real_name . (I means it do not filter out it)

I have a idea, but it is fit for less fields, if there is only one username field:

def get_queryset(self):
    username = self.request.query_params.get("username")
    if username == None or username == '':
        return User.objects.filter(
                is_admin=False,
                is_staff=False,
                is_superuser=False)
    else: 
        return User.objects.filter(
                is_admin=False,
                is_staff=False,
                is_superuser=False,
                username=username)

But there are so many fields, I can not write all judge conditions. I tried use

    return User.objects.filter(
            is_admin=False,
            is_staff=False,
            is_superuser=False,

            username__contains=username,
            real_name__contains=real_name,
            phone__contains=phone,
            company_name__contains=company_name
            ) 

But do not work too.

Is there a good way to realize this requirement?

You can create a dict then pass it using keyword expansions.

filters = {'{}__contains'.format(key): value
           for key, value in query_params.items()
           if value is not None}
return User.objects.filter(**filters)

If there is a pagination parameter, it could be excluded with:

filters = {'{}__contains'.format(key): value
               for key, value in query_params.items()
               if value is not None and key != "page"}

I hope this is what you are looking for.

from django.db.models import Q
obj_list = User.objects.filter(
                is_admin=False,
                is_staff=False,
                is_superuser=False,
                Q(username__contains=username)|
                Q(real_name__contains=real_name)|
                Q(phone__contains=phone) |
                Q(company_name__contains=company_name)
                )
return obj_list

let me know if this work for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM