在Django 1.6中将多个模型序列化为json的最佳方法是什么?

时间:2016-08-25 19:01:21

标签: python json serialization django-views

我有3个型号如下所示。

    class DocumentClass(models.Model):
        text = models.CharField(max_length=100)


    class DocumentGroup(models.Model):
        text = models.CharField(max_length=100)
        documentclass = models.ForeignKey(DocumentClass)


    class DocumentType(models.Model):
        text = models.CharField(max_length=100)
        documentgroup = models.ForeignKey(DocumentGroup)

我的目标是这样的:

[
    {
        'pk': 1,
        'model': 'DocumentClass',
        'fields':{
            'text':'DocumentClass1',
            'documentgroup':
            [
                {
                    'pk': 1,
                    'model': 'DocumentGroup'
                    'field':
                    {
                        'text':'DocumentGroup1'
                    }
                }
            ]
        }
    },
    {
        'pk': 2,
        'model': 'DocumentClass',
        'fields':{
            'text':'DocumentClass2'
        }
    }
]

我通常按

序列化模型
jsonstr = serializers.serialize("json", DocumentType.objects.all())

但是为了我的目标。我不知道。 作为标题。最好的方法是什么?

编辑: 上述模型的关系如下:

DocumentClass1
|-DocumentGroup1
| |-DocumentType1
| |-DocumentType2
| |-...
|-DocumentGroup2
| |-...
DocumentClass2
|-DocumentGroup...
| |-DocumentType...

3 个答案:

答案 0 :(得分:1)

如果模型相关

这需要更多自定义序列化,您必须使用Django Rest Framework's serializers

尝试继承ModelSerializer

class DocumentTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = DocumentType


class DocumentGroupSerializer(serializers.ModelSerializer):
    types = DocumentTypeSerializer(many=True)

    class Meta:
        model = DocumentGroup


class DocumentClassSerializer(serializers.ModelSerializer):
    groups = DocumentGroupSerializer(many=True)

    class Meta:
        model = DocumentClass


queryset = DocumentClass.objects.all()
serializer = DocumentClassSerializer(queryset, many=True)
json = JSONRenderer().render(serializer.data)

如果模型不相关

根据Django docsserialize()的第二个参数可以是"任何产生Django模型实例的迭代器"。

现在,您需要将3种实例作为迭代器传递。似乎Python的itertools.chain是首选方法,投票为here

所以你的电话看起来像是:

instances = list(chain(DocumentClass.objects.all(), DocumentGroup.objects.all(), DocumentType.objects.all())
jsonstr = serializers.serialize("json", instances)

答案 1 :(得分:0)

当我跟随@nofinator在&#34中回答;如果模型是相关的"部分一切正常,直到json = JSONRenderer().render(serializer.data)我遇到上述错误。我怎样才能消除它们?

AttributeError: Got AttributeError when attempting to get a value for field `documenttypes` on serializer `DocumentGroupSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `DocumentGroups` instance.
Original exception text was: 'DocumentGroups' object has no attribute 'documenttypes'.

这是我的serialize.py

from rest_framework import serializers
from .models import *


class DocumentTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = DocumentTypes
        fields = ('id', 'text')


class DocumentGroupSerializer(serializers.ModelSerializer):
    documenttypes = DocumentTypeSerializer(many=True)

    class Meta:
        model = DocumentGroups
        fields = ('id', 'text', 'documenttypes')


class DocumentClassSerializer(serializers.ModelSerializer):
    documentgroups = DocumentGroupSerializer(many=True)

    class Meta:
        model = DocumentClasses
        fields = ('id', 'text', 'documentgroups')

这是我的models.py

from django.db import models


class DocumentClasses(models.Model):
    text = models.CharField(max_length=100)


class DocumentGroups(models.Model):
    text = models.CharField(max_length=100)
    documentclass = models.ForeignKey(DocumentClasses)


class DocumentTypes(models.Model):
    text = models.CharField(max_length=100)
    documentgroup = models.ForeignKey(DocumentGroups)

更新。 当我尝试添加read_only=True我的serializer.py看起来像

from rest_framework import serializers
from .models import *

class DocumentTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = DocumentTypes
        fields = ('id', 'text', 'documentgroup')


class DocumentGroupSerializer(serializers.ModelSerializer):
    documenttypes = DocumentTypeSerializer(many=True, read_only=True)

    class Meta:
        model = DocumentGroups
        fields = ('id', 'text', 'documenttypes')


class DocumentClassSerializer(serializers.ModelSerializer):
    documentgroups = DocumentGroupSerializer(many=True, read_only=True)

    class Meta:
        model = DocumentClasses
        fields = ('id', 'text', 'documentgroups')

然后尝试:

queryset = DocumentClasses.objects.all()
serializer = DocumentClassSerializer(queryset, many=True)
json = JSONRenderer().render(serializer.data)

我只有'[{"id":1,"text":"class1"}]' 但这是我的预期:

[  
   {  
      "id":1,
      "text":"class1",
      "documentgroups":[  
         {  
            "id":1,
            "text":"group1",
            "documenttypes":[  
               {  
                  "id":1,
                  "text":"type1"
               }
            ]
         }
      ]
   }
]

答案 2 :(得分:0)

嗨@nofinator和其他像我这样的django菜鸟! 感谢@nofinator的最佳答案!对于像我这样的django新秀。如果您想使用django-rest-framework序列化查询集请勿忘记以在模型中使用** related_name **(不带**)属性,如下所示:

class DocumentClasses(models.Model):
    text = models.CharField(max_length=100)


class DocumentGroups(models.Model):
    text = models.CharField(max_length=100)
    documentclass = models.ForeignKey(DocumentClasses, **related_name**='documentgroups')


class DocumentTypes(models.Model):
    text = models.CharField(max_length=100)
    documentgroup = models.ForeignKey(DocumentGroups, **related_name**='documenttypes')

@nofinator和ralated_name结识了我的一天!百万谢谢!