I want to create Mixins for QuerySet objects that will by default filter out certain records (e.g. filter out "deleted" records, or filter out "unapproved" records, etc). I'd like those to be separate independent mixins. So in each of those, I override all() to filter out deleted or unapproved, etc. But, I also want to offer a method in the queryset to remove those filters or remove some part of those filters.
That's where this code comes in. After some examination of how QuerySets work, this seemed like the simplest method for "undoing" some filter in a queryset
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | """
Use this hack to remove a where clause from a queryset
It assumes the following internals:
QuerySet has something called a query
query has something called a 'where' which is a tree root
that tree root is of type WhereNode and has connector 'OR' or 'AND' and some number of children
each child can be a simple clause (Constraint) or another WhereNode with a bunch of kids of its own
"""
from django.db.models.sql.where import *
__all__ = ['remove_clause', ]
def remove_clause(queryset, field_name):
# Start the recursive fixin'
_remove_clause(queryset.query.where, field_name)
def _remove_clause(node, field_name):
if isinstance(node, WhereNode):
null_these = []
# look at each child and treat appropriately
for i, child in enumerate(node.children):
if isinstance(child, WhereNode):
_remove_clause(child, field_name)
elif isinstance(child, tuple) and isinstance(child[0], Constraint):
if child[0].field.name == field_name:
null_these.append(i)
# we have some children to "nullify"
for null_this in null_these:
if node.connector == 'AND':
node.children[null_this] = EverythingNode()
else:
node.children[null_this] = NothingNode()
|
More like this
- Stuff by NixonDash 1 month ago
- Add custom fields to the built-in Group model by jmoppel 3 months ago
- Month / Year SelectDateWidget based on django SelectDateWidget by pierreben 6 months, 2 weeks ago
- Python Django CRUD Example Tutorial by tuts_station 7 months ago
- Browser-native date input field by kytta 8 months, 2 weeks ago
Comments
This is good, but will not work from djang0 >= 1.9.0
#
Please login first before commenting.