问题
I have 3 models show as below.
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)
And my goal is something like this:
[
{
'pk': 1,
'model': 'DocumentClass',
'fields':{
'text':'DocumentClass1',
'documentgroup':
[
{
'pk': 1,
'model': 'DocumentGroup'
'field':
{
'text':'DocumentGroup1'
}
}
]
}
},
{
'pk': 2,
'model': 'DocumentClass',
'fields':{
'text':'DocumentClass2'
}
}
]
I usually serialize a model by
jsonstr = serializers.serialize("json", DocumentType.objects.all())
But for my goal. I have no idea. As the title. What is the best way to do that?
Edit: The relation of above models look like:
DocumentClass1
|-DocumentGroup1
| |-DocumentType1
| |-DocumentType2
| |-...
|-DocumentGroup2
| |-...
DocumentClass2
|-DocumentGroup...
| |-DocumentType...
回答1:
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)
回答2:
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"
}
]
}
]
}
]
回答3:
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!
来源:https://stackoverflow.com/questions/39152899/whats-the-best-way-to-serialize-more-than-one-model-to-json-in-django-1-6