Login

Q marshaller

Author:
SpikeekipS
Posted:
March 11, 2008
Language:
Python
Version:
.96
Tags:
model python q query
Score:
2 (after 2 ratings)

Django supports the serializing model objects, but does not support the serializing Q object like that,

q = Q(username__contains="findme") model0.objects.filter(q)

serialize(q) # X

so I wrote a little marshaller for Q, this is example,

from django.contrib.auth import models as django_models qs = django_query.Q(usernamecontains="spike") | django_query.Q(emailcontains="spike")

_m = QMarshaller() a = _m.dumps(qs) # a was serialized.

When call the similiar queries in page by page, you don't need to write additional code for creating same Q(s) for filtering models, just use the serialized Q as http querystring and in the next page unserialize and apply it. That is simple life.

  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
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# -*- 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("</%s>" % 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("</%s>" % 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("</%s>" % 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("</%s>" % 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("</%s>" % 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

More like this

  1. QSerializer with default to JSON input and output by asfaltboy 1 year, 9 months ago
  2. filtered ModelChoiceField queries by robharvey 7 years, 6 months ago
  3. serialize model object with related objects to dict by zakovinko 4 years, 7 months ago
  4. Improved YAML serializer for large databases by rspeer 6 years, 4 months ago
  5. Left Outer join Q object by karsu 8 years, 3 months ago

Comments

Please login first before commenting.