def put_Q_negations_to_leaves( query_filter: Q, negate: bool = False, debug: bool = False, ): negate_below = (negate != query_filter.negated) # XOR if debug: logger.info( f"put_Q_negations_to_leaves() query_filter:{query_filter}" f" negate:{negate} negate_below:{negate_below}" ) true_kwargs = { "_connector": query_filter.connector, "_negated": False, } new_children = [] for child in query_filter.children: if debug: logger.info(child.__repr__()) if not isinstance(child, Q): if negate_below: new_child = ~Q(child) else: new_child = child else: new_child = put_Q_negations_to_leaves(child, negate=negate_below) if debug: logger.info(new_child.__repr__()) new_children.append(new_child) if len(new_children) == 1: # One child if isinstance(new_children[0], Q): return new_children[0] else: true_kwargs["_negated"] = negate_below if negate_below: if true_kwargs["_connector"] == Q.AND: true_kwargs["_connector"] = Q.OR else: true_kwargs["_connector"] = Q.AND return Q(*new_children, **true_kwargs)