我对Django继承模型的序列化存在问题。例如
class Animal(models.Model):
color = models.CharField(max_length=50)
class Dog(Animal):
name = models.CharField(max_length=50)
...
# now I want to serialize Dog model with Animal inherited fields obviously included
print serializers.serialize('xml', Dog.objects.all())
并且只有狗模型被序列化。
我可以像
那样做all_objects = list(Animal.objects.all()) + list(Dog.objects.all())
print serializers.serialize('xml', all_objects)
但它看起来很难看,因为我的模型非常大,所以我必须使用SAX解析器,并且输出很难解析。
知道如何用父类序列化django模型吗?
**编辑:**在使用此patch之前,它可以正常工作。并解释为什么补丁存在“模型保存在反序列化期间过于积极地创建新的父类实例。模型上的原始保存现在跳过保存父类。”我认为应该有一个选项可以序列化“本地仅字段“默认情况下和第二个选项 - ”全部“ - 序列化所有继承的字段。
答案 0 :(得分:1)
您在补丁文档中找到了答案。
all_objects = list(Animal.objects.all()) + list(Dog.objects.all())
print serializers.serialize('xml', all_objects)
但是,如果将Animal
更改为抽象基类,它将起作用:
class Animal(models.Model):
color = models.CharField(max_length=50)
class Meta:
abstract = True
class Dog(Animal):
name = models.CharField(max_length=50)
这适用于Django 1.0。请参阅http://docs.djangoproject.com/en/dev/topics/db/models/。
答案 1 :(得分:1)
您需要一个自定义序列化程序来支持继承字段,因为Django的序列化程序只会序列化本地字段。
我在处理这个问题时最终写了自己的东西,随意复制它:https://github.com/zmathew/django-backbone/blob/master/backbone/serializers.py
为了自己使用它,您需要:
serializer = AllFieldsSerializer()
serializer.serialize(queryset, fields=fields)
print serializer.getvalue()
答案 2 :(得分:0)
你看过select_related()吗? 如在
serializers.serialize('xml', Dog.objects.select_related().all())
答案 3 :(得分:0)
您可以定义自定义序列化程序:
class DogSerializer(serializers.ModelSerializer):
class Meta:
model = Dog
fields = ('color','name')
使用它像:
serializer = DogSerializer(Dog.objects.all(),many = True)
print serializer.data在这里输入代码
答案 4 :(得分:0)
我有同样的问题,我编写了一个'小'查询集序列化程序,它导航继承树并返回序列化的所有字段。
它远非完美......但对我有用:)
a = QuerySetSerializer(MyModel, myqueryset)
a.serialize()
和片段:
from __future__ import unicode_literals
import json
import inspect
from django.core import serializers
from django.db.models.base import Model as DjangoBaseModel
class QuerySetSerializer(object):
def __init__(self, model, initial_queryset):
"""
@param model: The model of your queryset
@param initial_queryset: The queryset to serialize
"""
self.model = model
self.initial_queryset = initial_queryset
self.inheritance_tree = self._discover_inheritance_tree()
def serialize(self):
list_of_querysets = self._join_inheritance_tree_objects()
merged_querysets = self._zip_queryset_list(list_of_querysets)
result = []
for related_objects in merged_querysets:
result.append(self._serialize_related_objects(related_objects))
return json.dumps(result)
def _serialize_related_objects(self, related_objects):
"""
In this method, we serialize each instance using the django's serializer function as shown in :
See https://docs.djangoproject.com/en/1.10/topics/serialization/#inherited-models
However, it returns a list with mixed objects... Here we join those related objects into one single dict
"""
serialized_objects = []
for related_object in related_objects:
serialized_object = self._serialize_object(related_object)
fields = serialized_object['fields']
fields['pk'] = serialized_object['pk']
serialized_objects.append(fields)
merged_related_objects = {k: v for d in serialized_objects for k, v in d.items()}
return merged_related_objects
def _serialize_object(self, obj):
data = serializers.serialize('json', [obj, ])
struct = json.loads(data)
return struct[0]
def _discover_inheritance_tree(self):
# We need to find the inheritance tree which excludes abstract classes,
# so we can then join them when serializing the instance
return [x for x in inspect.getmro(self.model) if x is not object and x is not DjangoBaseModel and not x._meta.abstract]
def _join_inheritance_tree_objects(self):
"""
Here we join the required querysets from the non abstract inherited models, which we need so we are able to
serialize them.
Lets say that MyUser inherits from Customer and customer inherits from django's User model
This will return [list(MyUser.objects.filter(...), list(Customer.objects.filter(...), list(User.objects.filter(...)
"""
initial_ids = self._get_initial_ids()
inheritance__querysets = [list(x.objects.filter(id__in=initial_ids).order_by("id")) for x in self.inheritance_tree]
return inheritance__querysets
def _zip_queryset_list(self, list_of_querysets):
"""
At this stage, we have something like:
(
[MyUser1, MyUser2, MyUser3],
[Customer1, Customer2, Customer3],
[User1, User2, User3]
)
And to make it easier to work with, we 'zip' the list of lists so it looks like:
(
[MyUser1, Customer1, User1],
[MyUser2, Customer2, User2],
[MyUser3, Customer3, User3],
)
"""
return zip(*list_of_querysets)
def _get_initial_ids(self):
"""
Returns a list of ids of the initial queryset
"""
return self.initial_queryset.order_by("id").values_list("id", flat=True)