如何在DRF中正确序列化一对多关系
我一直在尝试使用DRF(Django REST框架)来序列化和反序列化一些数据,但我不太确定哪里出了问题。
以下是我的模型:
from django.db import models
class FooA(models.Model):
propA = models.CharField(max_length=30)
class FooB(models.Model):
propB = models.CharField(max_lenght=30)
propC = models.ForeignKey(FooC, related_name='fooBs')
class FooC(models.Model):
propC = models.CharField(max_lenght=30)
fooAs = models.ManyToMany(FooA, null=True, blank=True)
以下是我的序列化器:
from rest_framework import serializers
from myModule import models
class FooASerializer(serializers.ModelSerializer):
class Meta:
model = models.FooA
fields = ('propA',)
class FooBSerializer(serializers.ModelSerializer):
class Meta:
model = models.FooB
fields = ('propB',)
class FooCSerializer(serializers.ModelSerializer):
fooBs = FooBSerializer(many=True)
fooAs = FooASerializer(many=True, required=False)
class Meta:
model = models.FooC
fields = ('fooAs', 'fooBs',)
这是我的“视图”:
from rest_framework import generics
from .serializers import FooCSerializer
from .models import FooC
class FooCList(generics.ListCreateAPIView):
model = FooC
serializer_class = FooCSerializer
最后,这是我的路由设置:
from django.conf.urls import patterns, url, include
from .views import FooCList
urlpatterns = patterns('',
url(r'^foocs/', FooCList.as_view())
)
我想做的是通过管理员界面创建一些数据,然后去DRF的API浏览器,复制一个FooC对象的JSON,稍微修改一下,测试能否成功将其反序列化为FooC对象。
这是我所做的:
>>> from rest_framework.compat import BytesIO
>>> from rest_framework.parsers import JSONParser
>>> from myApp.serializers import FooCSerializer
>>>
>>> content = '<slightly modified JSON copied from the DRF api browser>'
>>> stream = BytesIO(content)
>>> data = JSONParser().parse(stream)
>>> serializer = FooCSerializer(data=data)
>>> serializer.is_valid()
True
>>> serializer.save()
ValueError: Cannot add "<FooA: fooA>": instance is on database "default", value is on database "None"
注意,它确实在我的数据库中创建了一个新的FooC实例,但并没有创建它的“嵌套”类(也就是FooC有关系的类)。
所以我有几个问题:
1) 这是预期的结果吗? 我原本希望它能“级联”创建所有相关的内容。
2) 如果这是设计使然,我在构建客户端时应该怎么做? 我的意思是,我原本期待能打开一个表单,在同一个表单中创建FooC及其所有相关实例。
谢谢大家!
1 个回答
0
简短回答:
1) 是的。
2) 有一些可能的解决办法。
为了让你明白我为什么对第一个问题回答“是”,我建议你去看看这里的解释,作者是DRF的创始人Tom Christie,链接在这里:https://groups.google.com/forum/#!msg/django-rest-framework/vCl2I_EzJnE/qwRdIdxiUe4J。
至于解决办法,你可以选择:
1) 使用pre_save方法,在一个循环中创建你的嵌套对象,然后把它们的主键(PK)添加到当前的FooC实例中。
2) 为你的嵌套类创建一个视图,然后从那个视图调用方法,传入你请求中的相应数据。
希望这对你有帮助 :)