我有2个型号:
from django.db import models
STATUSES = (
('f', 'Finished'),
)
class Battery(models.Model):
energy = models.CharField(max_length=10)
current = models.CharField(max_length=10)
class Charger(models.Model):
status = models.CharField(max_length=1, choices=STATUSES)
我想创建序列化器,将这两个模型序列化在一起。我的serializers.py:
from rest_framework import serializers
from .models import Battery, Charger
class BatterySerializer(serializers.ModelSerializer):
class Meta:
model = Battery
class ChargerSerializer(serializers.ModelSerializer):
status = serializers.SerializerMethodField()
class Meta:
model = Charger
def get_status(self, obj):
return obj.get_status_display()
class DeviceSerializer(serializers.Serializer):
battery = BatterySerializer()
charger = ChargerSerializer()
some_field = serializers.CharField()
由于Charger模型在状态字段中有选择,我添加SerializerMethodField以显示完整状态。然后我创建一个这样的视图:
class DeviceView(APIView):
def get(self, request, format=None):
battery = Battery.objects.get(id=1)
charger = Charger.objects.get(id=1)
battery_serializer = BatterySerializer(battery)
charger_serializer = ChargerSerializer(charger)
serializer = DeviceSerializer(data={
'battery': battery_serializer.data,
'charger': charger_serializer.data,
'some_field': 'some_text'
})
if serializer.is_valid():
return Response(serializer.validated_data)
else:
return Response(status = 500)
但是当我调用此视图时,它返回带有空充电器字段的json:
{
"battery": {
"energy": "12",
"current": "34"
},
"charger": {},
"some_field": "some_text"
}
但是当我创建一个仅序列化Charger模型的视图时:
class ChargerView(APIView):
def get(self, request, format=None):
charger = Charger.objects.get(id=1)
charger_serializer = ChargerSerializer(charger)
return Response(charger_serializer.data)
它有效并返回此json:
{
"id": 1,
"status": "Finished"
}
为什么会这样?我在哪里弄错了?
答案 0 :(得分:6)
查看Serializers
的文档:
instance
。 (link) data
。(link) instance
和data
。(link) 考虑一下你的情况,我认为你不需要选项2和3,因为你有battery
和charger
个实例,你需要将它们序列化。您没有创建新实例,也不必验证它,因此不需要将其作为data
传递。
有两种方法可以做到这一点:
1.创建一个类Device
,以便您可以创建它的实例,然后使用DeviceSerializer
对其进行序列化:
class Device(object):
def __init__(self, battery, charger, some_field):
self.battery = battery
self.charger = charger
self.some_field = some_field
class DeviceView(APIView):
# then in the DeviceView you could create an instance and pass to the serializer
def get(self, request, format=None):
battery = Battery.objects.get(id=1)
charger = Charger.objects.get(id=1)
device = Device(battery=battery, charger=charger, some_field='some_text')
serializer = DeviceSerializer(instance=device)
return Response(serializer.data)
2.如果您不想创建新课程,可以直接创建dict
并将其作为实例传递:
class DeviceView(APIView):
def get(self, request, format=None):
battery = Battery.objects.get(id=1)
charger = Charger.objects.get(id=1)
# create a dict with required objects and pass it as instance of serializer
device = {'battery': battery, 'charger': charger, 'some_field': 'some_text'}
serializer = DeviceSerializer(instance=device)
return Response(serializer.data)
答案 1 :(得分:1)
好像你正在做你不必做的工作。如果您在将充电器传递到DeviceSerializer
之前对其进行序列化,那么您实际上正在传递dict
,而不是Charger
个实例,dict
没有{{} 1}}方法。您应该直接传递get_status_display
和Battery
:
Charger
请注意,您还可以使用CharField:
替换SerializerMethodField来简化class DeviceView(APIView):
def get(self, request, format=None):
battery = Battery.objects.get(id=1)
charger = Charger.objects.get(id=1)
serializer = DeviceSerializer(instance={
'battery': battery,
'charger': charger,
'some_field': 'some_text',
})
return Response(serializer.data)
编辑:正如AKS指出的那样,序列化时应该传递class ChargerSerializer(serializers.ModelSerializer):
status = serializers.CharField(source='get_status_display')
class Meta:
model = Charger
而不是instance
序列化(data
用于反序列化),并且您不需要检查data
答案 2 :(得分:1)
在创建序列化程序实例时传递关键字数据,仅在反序列化数据时使用。 您应该使用包含所需字段的对象创建DeviceSerializer。 我没有测试过,但可能是这样的
class Device(object):
def __init__(self, battery, charger, name, ):
self.battery = battery
self.charger = charger
self.some_field = name
class DeviceView(APIView):
def get(self, request, format=None):
d=Device(Battery.objects.get(id=1),Charger.objects.get(id=1),"somename")
serializer = DeviceSerializer(d)
return Response(serializer.data)