我有通用外键的模型,我想序列化该模型。
model.py
:
class AddressType(models.Model):
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type','object_id')
def __unicode__(self):
return u'%s' % str(self.content_type)
class AddressBook(TimeStampedModel):
class Meta:
db_table = 'address_book'
uuid = UUIDField(auto=True)
address_tag = models.CharField(null=True, blank=True, max_length=20)
# should be a generic foreign key
address_object_type = GenericRelation(AddressType)
address1 = models.CharField(
verbose_name='Address1',
max_length=200,
)
address2 = models.CharField(
verbose_name='Address2',
max_length=200,
)
serializer.py
:
class AddressBookSerializer(serializers.ModelSerializer):
class Meta:
model = AddressBook
fields = ('id','uuid','address_tag','address_object_type','address1','address2')
如何在上面的模型上序列化JSON?
答案 0 :(得分:3)
documentation中完整描述了这种情况。
因此,如果您想序列化AddressType
,则需要实现以下内容:
class ContentObjectRelatedField(serializers.RelatedField):
"""
A custom field to use for the `content_object` generic relationship.
"""
def to_representation(self, value):
"""
Serialize tagged objects to a simple textual representation.
"""
if isinstance(value, Bookmark):
return 'Bookmark: ' + value.url
elif isinstance(value, Note):
return 'Note: ' + value.text
raise Exception('Unexpected type of tagged object')
其中Bookmark
和Note
是可能包含相关内容的对象。
如果您想序列化AddressBook
,可以尝试这样做:
class AddressBookSerializer(serializers.ModelSerializer):
address_object_type = ContentObjectRelatedField()
class Meta:
model = AddressBook
fields = ('id','uuid','address_tag','address_object_type','address1','address2')
答案 1 :(得分:0)
我更喜欢使用第三方(rest-framework-generic-relations),如documentation中所述。
from generic_relations.relations import GenericRelatedField
class TagSerializer(serializers.ModelSerializer):
"""
A `TaggedItem` serializer with a `GenericRelatedField` mapping all possible
models to their respective serializers.
"""
tagged_object = GenericRelatedField({
Bookmark: BookmarkSerializer(),
Note: NoteSerializer()
})
class Meta:
model = TaggedItem
fields = ('tag_name', 'tagged_object')
答案 2 :(得分:0)
如果您的代码更加结构化,即每个应用程序都有其serializers.py,并且序列化程序的命名遵循约定(即[ModelName] Serializer),则可以使用动态导入来避免if ... elif ... else ...
逻辑,从而避免松动耦合:
from django.utils.module_loading import import_string
class ContentObjectRelatedField(serializers.RelatedField):
"""
A custom field to serialize generic relations
"""
def to_representation(self, object):
object_app = object._meta.app_label
object_name = object._meta.object_name
serializer_module_path = f'{object_app}.serializers.{object_name}Serializer'
serializer_class = import_string(serializer_module_path)
return serializer_class(object).data