2009-07-15 21 views
7

Django継承モデルのシリアル化に問題があります。たとえば、継承モデルの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が適用される前に正常に動作するために使用します。また、パッチが存在する理由の説明 "モデルの保存は、逆シリアル化中に新しい親クラスインスタンスを作成することに対してあまりにも積極的でした。モデルのRaw保存は親クラスの保存をスキップします。"ローカルすべての継承されたフィールドをシリアル化します。

+1

データベースにデータをマッピングするために設計され、最終的には、何かをシリアル化したいのはなぜ? –

答えて

0

select_related()を見ましたか? as

serializers.serialize('xml', Dog.objects.select_related().all()) 
+1

これは役に立ちません: 'select_related'はdjangoシリアライザの親モデルの処理に影響しません。 – Wogan

+0

'select_related'は最適化です。 QuerySetによって余分なデータは返されません。参照されるデータを取得するためにSQLクエリを(潜在的に)使用します。 上記のケースでは、他のモデルの 'Dog'や' Animal'を通じた参照がないので、 'select_related()'の使用には全く利点はありません。 –

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

Djangoのシリアライザはローカルフィールドのみをシリアル化するため、継承されたフィールドをサポートするにはカスタムシリアライザが必要です。

私はそれをコピーすること自由に感じ、この問題に対処するとき、自分を書くことになった:https://github.com/zmathew/django-backbone/blob/master/backbone/serializers.py

独自にそれを使用するためには、あなたは何をする必要があります。

serializer = AllFieldsSerializer() 
serializer.serialize(queryset, fields=fields) 
print serializer.getvalue() 
+1

申し訳ありませんが、リンクが壊れています – abrunet

+0

https://github.com/zmathew/django-backbone/blob/351fc75797bc3c75d2aa5c582089eb39ebb6f19a/backbone/serializers.py – test30

0

することはできカスタムシリアライザを定義します。
シリアライザ= DogSerializer(Dog.objects.all()、多くの=真):

class DogSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Dog 
     fields = ('color','name') 

は次のようにそれを使用します print serializer.dataここにコードを入力

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) 
関連する問題