序列化Python类中的@property方法
有没有办法让Django模型类中的任何@property定义在进行JSON序列化时被传递给JSON序列化器呢?
举个例子:
class FooBar(object.Model)
name = models.CharField(...)
@property
def foo(self):
return "My name is %s" %self.name
想要序列化成:
[{
'name' : 'Test User',
'foo' : 'My name is Test User',
},]
5 个回答
7
这是M. Rafay Aleem、Wtowers和caots的答案结合在一起的内容。这个方法遵循了“不要重复自己”的原则,让你只需要指定额外的属性,而不是像caots的版本那样需要列出所有的字段和属性。
from django.core.serializers.json import Serializer as JsonSerializer
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.base import Serializer as BaseSerializer
class ExtBaseSerializer(BaseSerializer):
def serialize(self, queryset, **options):
self.selected_props = options.pop('props')
return super(ExtBaseSerializer, self).serialize(queryset, **options)
def serialize_property(self, obj):
model = type(obj)
for field in self.selected_props:
if hasattr(model, field) and type(getattr(model, field)) == property:
self.handle_prop(obj, field)
def handle_prop(self, obj, field):
self._current[field] = getattr(obj, field)
def end_object(self, obj):
self.serialize_property(obj)
super(ExtBaseSerializer, self).end_object(obj)
class ExtPythonSerializer(ExtBaseSerializer, PythonSerializer):
pass
class ExtJsonSerializer(ExtPythonSerializer, JsonSerializer):
pass
使用方法如下:
ExtJsonSerializer().serialize(MyModel.objects.all(), props=['property_1', ...])
7
由M. Rafay Aleem和Wtower提出的解决方案效果很好,但它重复了很多代码。这里有一个改进版本:
from django.core.serializers.base import Serializer as BaseSerializer
from django.core.serializers.python import Serializer as PythonSerializer
from django.core.serializers.json import Serializer as JsonSerializer
class ExtBaseSerializer(BaseSerializer):
def serialize_property(self, obj):
model = type(obj)
for field in self.selected_fields:
if hasattr(model, field) and type(getattr(model, field)) == property:
self.handle_prop(obj, field)
def handle_prop(self, obj, field):
self._current[field] = getattr(obj, field)
def end_object(self, obj):
self.serialize_property(obj)
super(ExtBaseSerializer, self).end_object(obj)
class ExtPythonSerializer(ExtBaseSerializer, PythonSerializer):
pass
class ExtJsonSerializer(ExtPythonSerializer, JsonSerializer):
pass
使用方法:
ExtJsonSerializer().serialize(MyModel.objects.all(), fields=['field_name_1', 'property_1' ...])
13
你可以在Django中扩展序列化器,操作起来并不复杂。这里有一个自定义的序列化器,它可以接收一个查询集和一组属性(可以是字段,也可以不是),然后返回JSON格式的数据。
from StringIO import StringIO
from django.core.serializers.json import Serializer
class MySerializer(Serializer):
def serialize(self, queryset, list_of_attributes, **options):
self.options = options
self.stream = options.get("stream", StringIO())
self.start_serialization()
for obj in queryset:
self.start_object(obj)
for field in list_of_attributes:
self.handle_field(obj, field)
self.end_object(obj)
self.end_serialization()
return self.getvalue()
def handle_field(self, obj, field):
self._current[field] = getattr(obj, field)
使用方法:
>>> MySerializer().serialize(MyModel.objects.all(), ["field1", "property2", ...])
当然,这样做可能比直接写一个简单的JSON序列化器要麻烦一些,但可能没有你自己写一个XML序列化器那么复杂(因为你还需要重新定义“handle_field”来适应XML的情况,并且还要更改基类来实现这一点)。