What's the best way to serialize more than one model to json in Django 1.6?

筅森魡賤 提交于 2019-12-07 07:49:27
nofinator

If The Models Are Related

This will require some more customized serialization, for which you will have to use Django Rest Framework's serializers.

Try subclassing 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)

If The Models Are Not Related

According to the Django docs, the 2nd argument to serialize() can be "any iterator that yields Django model instances".

Now you'll need to pass your 3 kinds of instances as an iterator. It seems like Python's itertools.chain is the preferred method, as voted here.

So your call would look something like:

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

As I follow by @nofinator's answer in "If The Models Are Related" section everything looks fine until json = JSONRenderer().render(serializer.data)I got above errors. How can I eliminate them?

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'.

Here is my 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')

And this is my 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)

Update. When I try to add read_only=True my serializer.py look like

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')

Then try:

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

I got only '[{"id":1,"text":"class1"}]' But this is my expected:

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

Hi @nofinator and other django rookie like me! Thanks @nofinator for the great answer! And for django rookies like me. If you want to use django-rest-framework to serialize queryset DO NOT FORGET to use the ** related_name **(without ** ) attribute in the model like this:

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 and ralated_name made my day! Million thanks!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!