copser
copser

Reputation: 2641

chain filter query params

I know it's a know subject but hear me out, I'm currently filter on query_params in my view like this:

filter_date = self.request.query_params.get('filter_date', None)
if filter_date is not None:
   queryset = queryset.filter(next_action_date__gte=filter_date)

return queryset

and I'm showing my contacts by next_action_date, now I have this custom data structure and I need to add it to this filter so it will show my contacts from most important to unimportant, I've tried to add it to the filter but I'm not getting any data, so how can I appropriately get this done, can someone show me?

This is my get_queryset:

def get_queryset(self):
    queryset = LeadContact.objects.none()
    user = self.request.user
    if user.has_perm('cms_sales.can_view_full_lead_contact_list'):
        queryset = LeadContact.objects.all()
    elif user.has_perm('cms_sales.can_view_lead_contact'):
        queryset = LeadContact.objects.filter(account_handler=user)

    filter_date = self.request.query_params.get('filter_date', None)

    # This is the custom ordering data structure
    virgin_data = LeadContact.objects.filter(status=LeadContactConstants.STATUS_PRISTINE)
    contacted_data = LeadContact.objects.filter(status=LeadContactConstants.STATUS_CONTACTED)
    qualified_data = LeadContact.objects.filter(status=LeadContactConstants.STATUS_QUALIFIED)
    client_data = LeadContact.objects.filter(status=LeadContactConstants.STATUS_CLIENT)
    # This needs to be added to the filter so it will properly order
    # contacts
    order_data = list(client_data) + list(qualified_data) + list(contacted_data) + list(virgin_data)

    if filter_date is not None:
        queryset = queryset.filter(next_action_date__gte=filter_date)

    return queryset

Upvotes: 0

Views: 339

Answers (1)

Mateusz Knapczyk
Mateusz Knapczyk

Reputation: 295

If you need QuerySet as a result, try with queryset = queryset.filter(next_action_date__gte=filter_date).order_by('status'), but it probably won't be your desired order.

But if you need just a filtered, sorted list (not a QuerySet), you can apply filter first, then get contacts by status and chain them all together.

def get_queryset(self):
    queryset = LeadContact.objects.none()
    user = self.request.user
    if user.has_perm('cms_sales.can_view_full_lead_contact_list'):
        queryset = LeadContact.objects.all()
    elif user.has_perm('cms_sales.can_view_lead_contact'):
        queryset = LeadContact.objects.filter(account_handler=user)

    filter_date = self.request.query_params.get('filter_date', None)
    if filter_date is not None:
        queryset = queryset.filter(next_action_date__gte=filter_date)

    # Filter our queryset already filtered by date (if given)
    virgin_data = list(queryset.filter(status=LeadContactConstants.STATUS_PRISTINE))
    contacted_data = list(queryset.filter(status=LeadContactConstants.STATUS_CONTACTED))
    qualified_data = list(queryset.filter(status=LeadContactConstants.STATUS_QUALIFIED))
    client_data = list(queryset.filter(status=LeadContactConstants.STATUS_CLIENT))
    # Just add them together
    order_data = client_data + qualified_data + contacted_data + virgin_data    

    return order_data

EDIT

I have found a way nicer solution here.

order = [
    LeadContactConstants.STATUS_CLIENT,
    LeadContactConstants.STATUS_QUALIFIED,
    LeadContactConstants.STATUS_CONTACTED,
    LeadContactConstants.STATUS_PRISTINE
]
order_data = sorted(queryset, key = lambda p: order.index(p.status))

Upvotes: 1

Related Questions