I have a third-party function which gives me a filtered queryset (e.g. records with 'valid'=True) but I want to remove a particular condition (e.g. to have all records, both valid and invalid).
Is there a way to remove a filter condition to an already-filtered queryset?
E.g.
only_valid = MyModel.objects.filter(valid=True)
all_records = only_valid.**remove_filter**('valid')
(I know that it would be better to define 'all_records' before 'only_valid', but this is just an example...)
Although there is no official way to do this using filter notation, you may easily do it with Q-notation. For example, if you ensure that third-part function returns a Q object, not a filtered QuerySet, you may do the following:
q = ThirdParty()
q = q | Q(valid=False)
And the resulting SQL conditions will be joined using OR operator.
From the docs:
Each time you refine a QuerySet, you get a brand-new QuerySet that is in no way bound to the previous QuerySet. Each refinement creates a separate and distinct QuerySet that can be stored, used and reused.
I doubt therefore, that there is a standard way to do it. You could dig into the code, see, what filter()
does and try a bit. If that doesn't help, my assumption is, you're out of luck and need to re-build the query yourself.
Use this function
from django.db.models import Q
def remove_filter(lookup, queryset):
"""
Remove filter lookup in queryset
```
>>> queryset = User.objects.filter(email='[email protected]')
>>> queryset.count()
1
>>> remove_filter('email', queryset)
>>> queryset.count()
1000
```
"""
query = queryset.query
q = Q(**{lookup: None})
clause, _ = query._add_q(q, self.used_aliases)
def filter_lookups(child):
return child.lhs.target != clause.children[0].lhs.target
query.where.children = list(filter(filter_lookups, query.where.children))
Here's what I did in a similar case.
all_records = MyModel.objects.all()
only_valid = MyModel.objects.filter(valid=True)
only_valid.original = all_records
...
all_records = only_valid.original
Obviously this clears any other filters too so it won't be right for every case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With