# Path: advanced_filters/q_serializer.py
# class QSerializer:
#     """
#     A Q object serializer base class. Pass base64=True when initializing
#     to Base-64 encode/decode the returned/passed string.
# 
#     By default the class provides loads/dumps methods that wrap around
#     json serialization, but they may be easily overwritten to serialize
#     into other formats (i.e XML, YAML, etc...)
#     """
#     b64_enabled = False
# 
#     def __init__(self, base64=False):
#         if base64:
#             self.b64_enabled = True
# 
#     @staticmethod
#     def _is_range(qtuple):
#         return qtuple[0].endswith("__range") and len(qtuple[1]) == 2
# 
#     def prepare_value(self, qtuple):
#         if self._is_range(qtuple):
#             qtuple[1][0] = qtuple[1][0] or min_ts
#             qtuple[1][1] = qtuple[1][1] or max_ts
#             qtuple[1] = (datetime.fromtimestamp(qtuple[1][0]),
#                          datetime.fromtimestamp(qtuple[1][1]))
#         return qtuple
# 
#     def serialize(self, q):
#         """
#         Serialize a Q object into a (possibly nested) dict.
#         """
#         children = []
#         for child in q.children:
#             if isinstance(child, Q):
#                 children.append(self.serialize(child))
#             else:
#                 children.append(child)
#         serialized = q.__dict__
#         serialized['children'] = children
#         return serialized
# 
#     def deserialize(self, d):
#         """
#         De-serialize a Q object from a (possibly nested) dict.
#         """
#         children = []
#         for child in d.pop('children'):
#             if isinstance(child, dict):
#                 children.append(self.deserialize(child))
#             else:
#                 children.append(self.prepare_value(child))
#         query = Q()
#         query.children = children
#         query.connector = d['connector']
#         query.negated = d['negated']
#         if 'subtree_parents' in d:
#             query.subtree_parents = d['subtree_parents']
#         return query
# 
#     def get_field_values_list(self, d):
#         """
#         Iterate over a (possibly nested) dict, and return a list
#         of all children queries, as a dict of the following structure:
#         {
#             'field': 'some_field__iexact',
#             'value': 'some_value',
#             'value_from': 'optional_range_val1',
#             'value_to': 'optional_range_val2',
#             'negate': True,
#         }
# 
#         OR relations are expressed as an extra "line" between queries.
#         """
#         fields = []
#         children = d.get('children', [])
#         for child in children:
#             if isinstance(child, dict):
#                 fields.extend(self.get_field_values_list(child))
#             else:
#                 f = {'field': child[0], 'value': child[1]}
#                 if self._is_range(child):
#                     f['value_from'] = child[1][0]
#                     f['value_to'] = child[1][1]
#                 f['negate'] = d.get('negated', False)
#                 fields.append(f)
# 
#             # add _OR line
#             if d['connector'] == 'OR' and children[-1] != child:
#                 fields.append({'field': '_OR', 'value': 'null'})
#         return fields
# 
#     def dumps(self, obj):
#         if not isinstance(obj, Q):
#             raise SerializationError
#         string = json.dumps(self.serialize(obj), default=dt2ts)
#         if self.b64_enabled:
#             return base64.b64encode(string.encode("latin-1")).decode("utf-8")
#         return string
# 
#     def loads(self, string, raw=False):
#         if self.b64_enabled:
#             d = json.loads(base64.b64decode(string))
#         else:
#             d = json.loads(string)
#         if raw:
#             return d
#         return self.deserialize(d)


from django.conf import settings
from django.db import models
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from .q_serializer import QSerializer
    users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_('Users'))
    groups = models.ManyToManyField('auth.Group', blank=True, verbose_name=_('Groups'))

    objects = UserLookupManager()

    b64_query = models.CharField(max_length=2048)
    model = models.CharField(max_length=64, blank=True, null=True)

    @property
    def query(self):
        """
        De-serialize, decode and return an ORM query stored in b64_query.
        """
        if not self.b64_query:
            return None
        s = QSerializer(base64=True)
        return s.loads(self.b64_query)

    @query.setter
    def query(self, value):
        """
        Serialize an ORM query, Base-64 encode it and set it to
        the b64_query field
        """
        if not isinstance(value, Q):
            raise Exception('Must only be passed a Django (Q)uery object')
        s = QSerializer(base64=True)
        self.b64_query = s.dumps(value)

    def list_fields(self):

# Path: advanced_filters/q_serializer.py
# class QSerializer:
#     """
#     A Q object serializer base class. Pass base64=True when initializing
#     to Base-64 encode/decode the returned/passed string.
# 
#     By default the class provides loads/dumps methods that wrap around
#     json serialization, but they may be easily overwritten to serialize
#     into other formats (i.e XML, YAML, etc...)
#     """
#     b64_enabled = False
# 
#     def __init__(self, base64=False):
#         if base64:
#             self.b64_enabled = True
# 
#     @staticmethod
#     def _is_range(qtuple):
#         return qtuple[0].endswith("__range") and len(qtuple[1]) == 2
# 
#     def prepare_value(self, qtuple):
#         if self._is_range(qtuple):
#             qtuple[1][0] = qtuple[1][0] or min_ts
#             qtuple[1][1] = qtuple[1][1] or max_ts
#             qtuple[1] = (datetime.fromtimestamp(qtuple[1][0]),
#                          datetime.fromtimestamp(qtuple[1][1]))
#         return qtuple
# 
#     def serialize(self, q):
#         """
#         Serialize a Q object into a (possibly nested) dict.
#         """
#         children = []
#         for child in q.children:
#             if isinstance(child, Q):
#                 children.append(self.serialize(child))
#             else:
#                 children.append(child)
#         serialized = q.__dict__
#         serialized['children'] = children
#         return serialized
# 
#     def deserialize(self, d):
#         """
#         De-serialize a Q object from a (possibly nested) dict.
#         """
#         children = []
#         for child in d.pop('children'):
#             if isinstance(child, dict):
#                 children.append(self.deserialize(child))
#             else:
#                 children.append(self.prepare_value(child))
#         query = Q()
#         query.children = children
#         query.connector = d['connector']
#         query.negated = d['negated']
#         if 'subtree_parents' in d:
#             query.subtree_parents = d['subtree_parents']
#         return query
# 
#     def get_field_values_list(self, d):
#         """
#         Iterate over a (possibly nested) dict, and return a list
#         of all children queries, as a dict of the following structure:
#         {
#             'field': 'some_field__iexact',
#             'value': 'some_value',
#             'value_from': 'optional_range_val1',
#             'value_to': 'optional_range_val2',
#             'negate': True,
#         }
# 
#         OR relations are expressed as an extra "line" between queries.
#         """
#         fields = []
#         children = d.get('children', [])
#         for child in children:
#             if isinstance(child, dict):
#                 fields.extend(self.get_field_values_list(child))
#             else:
#                 f = {'field': child[0], 'value': child[1]}
#                 if self._is_range(child):
#                     f['value_from'] = child[1][0]
#                     f['value_to'] = child[1][1]
#                 f['negate'] = d.get('negated', False)
#                 fields.append(f)
# 
#             # add _OR line
#             if d['connector'] == 'OR' and children[-1] != child:
#                 fields.append({'field': '_OR', 'value': 'null'})
#         return fields
# 
#     def dumps(self, obj):
#         if not isinstance(obj, Q):
#             raise SerializationError
#         string = json.dumps(self.serialize(obj), default=dt2ts)
#         if self.b64_enabled:
#             return base64.b64encode(string.encode("latin-1")).decode("utf-8")
#         return string
# 
#     def loads(self, string, raw=False):
#         if self.b64_enabled:
#             d = json.loads(base64.b64decode(string))
#         else:
#             d = json.loads(string)
#         if raw:
#             return d
#         return self.deserialize(d)


# Path: advanced_filters/models.py
from django.conf import settings
from django.db import models
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from .q_serializer import QSerializer

    users = models.ManyToManyField(settings.AUTH_USER_MODEL, blank=True, verbose_name=_('Users'))
    groups = models.ManyToManyField('auth.Group', blank=True, verbose_name=_('Groups'))

    objects = UserLookupManager()

    b64_query = models.CharField(max_length=2048)
    model = models.CharField(max_length=64, blank=True, null=True)

    @property
    def query(self):
        """
        De-serialize, decode and return an ORM query stored in b64_query.
        """
        if not self.b64_query:
            return None
        s = QSerializer(base64=True)
        return s.loads(self.b64_query)

    @query.setter
    def query(self, value):
        """
        Serialize an ORM query, Base-64 encode it and set it to
        the b64_query field
        """
        if not isinstance(value, Q):
            raise Exception('Must only be passed a Django (Q)uery object')
        s = QSerializer(base64=True)
        self.b64_query = s.dumps(value)

    def list_fields(self):

        s = QSerializer(base64=True)