0

Here is a sample model I have:

class Commission(models.Model):
  status                     = models.CharField(null=True, blank=True)
  customer_name              = models.CharField(null=True, blank=True)
  order_dat                  = models.CharField(null=True, blank=True)

For status, I can have up to 10 different status types, such as: requested, confirmed, paid...

If I want to build a way to dynamically filter all orders with a specific status with a specific customer, I would do the following:

sample_kwargs['status'] = 'active'
sample_kwargs['custom_name'] = 'John Doe'

Then get my results with the following:

all_commmissions = Commission.objects.filter(**sample_kwargs)

This all works well, but what I am now trying to do is is get all the customer's orders that are equal to multiple statuses. For example, I want all of John Doe's orders that are equal to both confirmed, and paid.

Normally I'd used the Q filter

  all_commmissions = Commission.objects.filter(
                     Q(status='confirmed') |
                     Q(status='paid'))

But this only allows me to hard code things in. How can I build a complex dynamic query (such as my sample_kwargs example) that uses OR? Or what is the best way I can achieve this? I could not find anything in the documentation. Thank you for your help.

3 Answers 3

1

You can simply change your status filter params to a list:

sample_kwargs['status__in'] = ['confirmed', 'paid']
sample_kwargs['custom_name'] = 'John Doe'
all_commmissions = Commission.objects.filter(**sample_kwargs)
Sign up to request clarification or add additional context in comments.

Comments

1

You can use the __in filter to return results that have a status in any of the values. setdefault can be used to create and append to a list of values dynamically

 sample_kwargs.setdefault('status__in', []).append('confirmed')
 sample_kwargs.setdefault('status__in', []).append('paid')

Comments

0

When you write

Commission.objects.filter(status='active', custom_name='John Doe')

this is basically a shortcut for

Commission.objects.filter(Q(status='active') & Q(custom_name='John Doe'))

Now, if you want to get Comissions with status either "paid" or "confirmed" and with custom_name "John Doe" via Q objects, you can do

Commission.objects.filter(
    (Q(status='active') | Q(status='confirmed')) & Q(custom_name='John Doe'))

However, as Neeraj showed, in your particular case you don't need to use Q objects and can simply use '__in' lookup for multiple statuses.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.