custom serialize and deserialize methods for meta

This commit is contained in:
Samuel Colvin 2015-09-07 20:16:17 +01:00
parent 41894131d3
commit d4eb1936b9
2 changed files with 32 additions and 3 deletions

View file

@ -70,6 +70,9 @@ class SearchEntry(models.Model):
meta_encoded = models.TextField()
def _deserialize_meta(self):
return json.loads(self.meta_encoded)
@property
def meta(self):
"""Returns the meta information stored with the search entry."""
@ -77,7 +80,7 @@ class SearchEntry(models.Model):
if hasattr(self, META_CACHE_KEY):
return getattr(self, META_CACHE_KEY)
# Decode the meta.
meta_value = json.loads(self.meta_encoded)
meta_value = self._deserialize_meta()
setattr(self, META_CACHE_KEY, meta_value)
return meta_value

View file

@ -2,7 +2,9 @@
from __future__ import unicode_literals
import sys, json
import sys
import json
import types
from itertools import chain, islice
from threading import local
from functools import wraps
@ -18,6 +20,8 @@ from django.db.models.query import QuerySet
from django.db.models.signals import post_save, pre_delete
from django.utils.encoding import force_text
from django.utils.html import strip_tags
from django.utils.functional import Promise
from django.core.serializers.json import DjangoJSONEncoder
try:
from importlib import import_module
except ImportError:
@ -26,6 +30,24 @@ except ImportError:
from watson.models import SearchEntry, has_int_pk
class UniversalEncoder(DjangoJSONEncoder):
ENCODER_BY_TYPE = {
set: list,
frozenset: list,
types.GeneratorType: list,
bytes: lambda o: o.decode('utf-8', errors='replace'),
}
def default(self, obj):
encoder = self.ENCODER_BY_TYPE.get(type(obj))
if encoder:
return encoder(obj)
elif isinstance(obj, Promise):
return force_text(obj)
else:
return super(UniversalEncoder, self).default(obj)
class SearchAdapterError(Exception):
"""Something went wrong with a search adapter."""
@ -439,6 +461,10 @@ class SearchEngine(object):
)
return object_id_int, search_entries
def serialize_meta(self, meta_obj):
"""serialise meta ready to be saved in "meta_encoded"."""
return json.dumps(meta_obj, cls=UniversalEncoder)
def _update_obj_index_iter(self, obj):
"""Either updates the given object index, or yields an unsaved search entry."""
model = obj.__class__
@ -452,7 +478,7 @@ class SearchEngine(object):
"description": adapter.get_description(obj),
"content": adapter.get_content(obj),
"url": adapter.get_url(obj),
"meta_encoded": json.dumps(adapter.get_meta(obj)),
"meta_encoded": self.serialize_meta(adapter.get_meta(obj)),
}
# Try to get the existing search entry.
object_id_int, search_entries = self._get_entries_for_obj(obj)