# -*- coding: utf-8 -*- import base64, string from xml.marshal.generic import Marshaller, Unmarshaller from django.db.models import Model from django.db.models.loading import get_model from django.db.models import query as django_query from copy import copy class QMarshaller (Marshaller) : def dumps (self, value, use_base64=False) : o = Marshaller.dumps(self, value) if use_base64 : return base64.b64encode(o) else : return o def _marshal(self, value, dict): if isinstance(value, Model) : meth = "m_django_object" return getattr(self, meth)(value, dict) return Marshaller._marshal(self, value, dict) def m_unicode (self, value, dict) : return self.m_string(value.encode("utf8"), dict) def m_django_object (self, object, dict) : name = "django_object" model_name = "%s.%s" % (object._meta.app_label, object._meta.module_name, ) L = ["<%s model=\"%s\" pk=\"%s\">" % (name, model_name, object.pk)] L.append("" % name) return L def m_condition (self, c, dict, ) : name = "condition" k, v, = c L = ["<%s key=\"%s\">" % (name, k, )] L = L + self._marshal(v, dict) L.append("" % name) return L def m_Q (self, q, dict, ) : name = "Q" L = ["<%s>" % (name, )] for c in q.kwargs.items() : L = L + self.m_condition(c, dict) L.append("" % name) return L def m_QOr (self, q, dict, ) : name = "QOr" L = ["<%s operator=\"%s\">" % (name, q.operator.strip(), )] for elem in q.args : L = L + self._marshal(elem, dict) L.append("" % name) return L def m_QAnd (self, q, dict, ) : name = "QAnd" L = ["<%s operator=\"%s\">" % (name, q.operator.strip(), )] for elem in q.args : L = L + self._marshal(elem, dict) L.append("" % name) return L class QUnmarshaller (Unmarshaller) : def __init__(self): self.unmarshal_meth.update( { "django_object": ("um_start_django_object", "um_end_django_object", ), "condition": ("um_start_condition", "um_end_condition", ), "Q": ("um_start_Q", "um_end_Q", ), "QOr": ("um_start_QOr", "um_end_QOr", ), "QAnd": ("um_start_QAnd", "um_end_QAnd", ), } ) Unmarshaller.__init__(self) def loads (self, s, use_base64=False) : if use_base64 : s = base64.b64decode(s) return Unmarshaller.loads(self, s) def um_end_string(self, name): ds = self.data_stack ds[-1] = string.join(ds[-1], "").encode("utf8") def um_start_QOr (self, name, attrs) : pass def um_end_QOr (self, name) : q = django_query.QOr() for i in self.data_stack : q = q | i self.data_stack[:] = [q] def um_start_QAnd (self, name, attrs) : pass def um_end_QAnd (self, name) : q = django_query.QAnd() for i in self.data_stack : q = q & i self.data_stack[:] = [q] def um_start_Q (self, name, attrs) : pass def um_end_Q (self, name) : if len(self.data_stack) < 1 : self.data_stack.append(django_query.Q()) else : key, value, = self.data_stack[-1] self.data_stack[-1] = django_query.Q(**{str(key): value}) def um_start_condition (self, name, attrs) : self.data_stack.append(attrs.get("key"), ) def um_end_condition (self, name) : key, value, = self.data_stack[-2:] self.data_stack[-2:] = [(key, value, )] def um_start_django_object (self, name, attrs) : m = get_model(*attrs.get("model").split(".")) self.data_stack.append(m.objects.get(pk=attrs.get("pk"))) def um_end_django_object (self, name) : pass if __name__ == "__main__" : import sys, base64 from django.contrib.auth import models as django_models qs = django_query.Q(username__contains="spike") | django_query.Q(email__contains="spike") _m = QMarshaller() a = _m.dumps(qs) print "Marshalled:" print a print _u = QUnmarshaller() qs = _u.loads(a) print "UnMarshalled:" print qs for i in qs.args : print i.kwargs print