我有一个引用Generic Relation的模型,我希望以详细的方式序列化。
class AType(models.Model):
foo = CharField()
class BType(models.Model):
bar = PositiveIntegerField()
class ToSerialize(models.Model):
scope_limit = models.Q(app_label="app", model="atype") | \
models.Q(app_label="app", model="btype")
content_type = models.ForeignKey(ContentType, limit_choices_to=scope_limit)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
我希望ToSerialize视图集的list方法的JSON看起来像:
[
{
"atype": { "id": 1, "foo": "a" }
},
{
"atype": { "id": 2, "foo": "b" }
},
{
"btype": { "id": 1, "bar": "1" }
},
{
"btype": { "id": 2, "bar": "2" }
}
]
我有没有办法让ToSerialize对象的视图集生成"条件字段"基于将实现此效果的content_type / object_id?
答案 0 :(得分:5)
class YourSerializer(serializers.ModelSerializer):
your_conditional_field = serializers.SerializerMethodField()
class Meta:
model = ToSerialize
def get_your_conditional_field(self, obj):
# do your conditional logic here
# and return appropriate result
return obj.content_type > obj.object_id
答案 1 :(得分:4)
没有一个答案能真正回答问题。
最简单的方法是默认添加所有字段,然后根据您的条件在序列化程序初始化时将其删除。
在下面的示例中,列出用户时我们不会退回电子邮件。
class UserSerializer():
fields = ('username', 'email')
class Meta:
model = User
def __init__(self, *args, **kwargs):
# Don't return emails when listing users
if kwargs['context']['view'].action == 'list':
del self.fields['email']
super().__init__(*args, **kwargs)
答案 2 :(得分:0)
推荐的方法是创建自定义 RelatedField 。检查DRF docs about generic relationships是一个很好的例子。在OP情况下,它看起来像这样:
class ABTypeRelatedField(serializers.RelatedField):
def to_representation(self, value):
"""
Serialize objects to a simple textual representation.
"""
if isinstance(value, AType):
return 'AType: ' + value.foo
elif isinstance(value, BType):
return 'BType: ' + value.bar
raise Exception('Unexpected type of content_object')
class ToSerializeSerializer(serializers.Serializer):
content_object = ABTypeRelatedField()