Reputation: 26896
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?
Upvotes: 0
Views: 173
Reputation: 599610
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"}
Upvotes: 2
Reputation: 1019
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.
Upvotes: -1