import json from collections import OrderedDict from tastypie.serializers import Serializer from tastypie import fields from tastypie.resources import Resource from django.core.serializers.json import DjangoJSONEncoder class OrderedSerializer(Serializer): def to_json(self, data, options=None): options = options or {} data = self.to_simple(data, options) return json.dumps(data, cls=DjangoJSONEncoder, sort_keys=False) def to_simple(self, data, options): if isinstance(data, Bundle): return OrderedDict((key, self.to_simple(val, options)) for (key, val) in data.data.items()) return super(OrderedSerializer, self).to_simple( data, options) class SomeResource(Resource): first_name = fields.fields.CharField(attribute='first_name',) last_name = fields.fields.CharField(attribute='last_name',) class Meta: resource_name = 'someresource' serializer = OrderedSerializer() field_order = ['first_name','last_name'] def full_dehydrate(self, bundle, for_list=False): """ Given a bundle with an object instance, extract the information from it to populate the resource. """ use_in = ['all', 'list' if for_list else 'detail'] """ Convert bundle data to OrderedDict """ bundle.data = OrderedDict(bundle.data) # Dehydrate each field. items = self.fields.items() ## make data ordered for field in self._meta.field_order: for field_name, field_object in items: if field_name == field: ## # If it's not for use in this mode, skip field_use_in = getattr(field_object, 'use_in', 'all') if callable(field_use_in): if not field_use_in(bundle): continue else: if field_use_in not in use_in: continue # A touch leaky but it makes URI resolution work. if getattr(field_object, 'dehydrated_type', None) == 'related': field_object.api_name = self._meta.api_name field_object.resource_name = self._meta.resource_name bundle.data[field_name] = field_object.dehydrate(bundle, for_list=for_list) # Check for an optional method to do further dehydration. method = getattr(self, "dehydrate_%s" % field_name, None) if method: bundle.data[field_name] = method(bundle) bundle = self.dehydrate(bundle) return bundle