Created
June 5, 2014 20:02
-
-
Save coddingtonbear/464fbdda2f0600ce4a77 to your computer and use it in GitHub Desktop.
Adam's Lovely-but-now-about-to-be-abandoned Serializer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import json | |
| from django.core import serializers | |
| from django.core.serializers.json import DjangoJSONEncoder | |
| from django.db.models import Model | |
| from django.db.models.query import QuerySet | |
| from django.template import ( | |
| Context, Library, Node, TemplateSyntaxError, Variable | |
| ) | |
| from django.utils.safestring import mark_safe | |
| from medley.util.caching import QuerySetList | |
| register = Library() | |
| class JSONSerializer(DjangoJSONEncoder): | |
| """ Special JSON allowing (naive) model serialization by __unicode__""" | |
| def default(self, obj): | |
| if isinstance(obj, Model): | |
| return unicode(obj) | |
| return super(JSONSerializer, self).default(obj) | |
| class SerializerNode(Node): | |
| INSTANCE_NAME = 'obj' | |
| def __init__(self, qs, fields=None): | |
| self._qs = qs | |
| self._fields = fields | |
| self._field_name_map = {} | |
| def get_synthetic_context(self, obj): | |
| return Context({ | |
| self.INSTANCE_NAME: obj, | |
| }) | |
| def get_synthetic_field_lookups(self, raw_fields): | |
| fields = [] | |
| for raw_field in raw_fields: | |
| if '=' in raw_field: | |
| field_parts = raw_field.split('=') | |
| assigned_name = field_parts[0] | |
| field = field_parts[1] | |
| else: | |
| # Return the same name in JSON that we're using for lookup | |
| assigned_name, field = raw_field, raw_field | |
| if field == '__unicode__': | |
| lookup_name = self.INSTANCE_NAME | |
| else: | |
| lookup_name = 'obj.%s' % field | |
| fields.append(lookup_name) | |
| self._field_name_map[lookup_name] = assigned_name | |
| return fields | |
| def get_actual_field_name(self, field): | |
| if field in self._field_name_map: | |
| return self._field_name_map[field] | |
| return field | |
| def model_serializer(self, queryset): | |
| return serializers.serialize( | |
| 'json', | |
| queryset, | |
| ) | |
| def dictionary_serializer(self, queryset): | |
| return json.dumps(queryset, cls=JSONSerializer) | |
| def get_queryset_and_serializer(self, context): | |
| queryset = Variable(self._qs).resolve(context) | |
| if not isinstance(queryset, (QuerySet, QuerySetList)): | |
| # We'll let people pass-in a single instance, but we'll | |
| # need to hand an iterable to Django's serializer: | |
| return [queryset], self.model_serializer | |
| elif self._fields is None: | |
| return queryset, self.model_serializer | |
| # If we've made it this far, we're using self._fields, and | |
| # will be creating a new dictionary that we will serialize | |
| dict_queryset = [] | |
| for instance in queryset: | |
| context = self.get_synthetic_context(instance) | |
| fields = self.get_synthetic_field_lookups(self._fields) | |
| obj = dict( | |
| ( | |
| self.get_actual_field_name(field), | |
| Variable(field).resolve(context) | |
| ) | |
| for field in fields | |
| ) | |
| dict_queryset.append(obj) | |
| return dict_queryset, self.dictionary_serializer | |
| def render(self, context): | |
| queryset, serializer = self.get_queryset_and_serializer(context) | |
| return mark_safe(serializer(queryset)) | |
| @register.tag | |
| def serialize(parser, token): | |
| try: | |
| parts = token.split_contents() | |
| qs = parts[1] | |
| fields = parts[2:] | |
| except ValueError: | |
| raise TemplateSyntaxError("Provide a single parameter only") | |
| return SerializerNode(qs, fields) |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
or