简体   繁体   English

Django Rest Framework不会序列化SerializerMethodField

[英]Django Rest Framework doesn't serialize SerializerMethodField

I have 2 models: 我有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)

And I want to create serializer that will serialize this 2 models together. 我想创建将这两个模型序列化在一起的序列化器。 My serializers.py: 我的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()

Because Charger model has choices in status field I add SerializerMethodField for displaying full status. 因为Charger模型在状态字段中有选择,所以我添加了SerializerMethodField以显示完整状态。 Then I create a view like this: 然后,我创建一个像这样的视图:

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)

But when I call this view it returns json with empty charger field: 但是当我调用此视图时,它返回带有空充电器字段的json:

{
    "battery": {
        "energy": "12",
        "current": "34"
    },
    "charger": {},
    "some_field": "some_text"
}

But when I create a view that serialize only Charger model: 但是,当我创建仅序列化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)

It works and it returns this json: 它有效,并返回此json:

{
    "id": 1,
    "status": "Finished"
}

Why this happens? 为什么会这样? Where did I make a mistake? 我在哪里弄错了?

Looking at the documentation of Serializers : 查看Serializers的文档:

  1. instance is passed when you have an object and you have to serialize it. instance在您有对象且必须对其进行序列化时传递。 (link) (链接)
  2. data is passed when you already have serialized data and you want to deserialize it and create an instance out of it. data时,你已经序列化的数据传递,你想反序列化和出它创建一个实例。 (link) (链接)
  3. both instance and data is passed when you have an instance and you want to update it. 当您拥有一个实例并想要更新它时, instancedata被传递。 (link) (链接)

Looking at your case, I don't think you need option 2 and 3 because you have the battery and charger instances and you need to serialize it together. 考虑到您的情况,我认为您不需要选项2和3,因为您有batterycharger实例,需要一起序列化。 You are not creating a new instance and you also don't have to validate it so passing it as data is not required. 您无需创建新实例,也不必验证它,因此不需要将其作为data传递。

There are two ways you could do this: 有两种方法可以执行此操作:

1.Create a class Device so you could create an instance of it and then serialize it using DeviceSerializer : 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.If you don't want to go with creating a new class you could directly create a dict and pass it as instance: 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)    

Seems like you're doing work you don't have to. 好像您在做不必要的工作。 If you serialize the charger before passing it to the DeviceSerializer , you're actually passing a dict , not a Charger instance, and the dict has no get_status_display method. 如果在将充电器传递给DeviceSerializer之前对其进行序列化,则实际上是传递的是dict ,而不是Charger实例,并且该dict没有get_status_display方法。 You should pass the Battery and Charger directly like so: 您应该像这样直接通过BatteryCharger

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)

Note that you can also simplify by replacing the SerializerMethodField with a CharField: 请注意,您还可以通过用CharField替换SerializerMethodField来简化操作:

class ChargerSerializer(serializers.ModelSerializer):
    status = serializers.CharField(source='get_status_display')

    class Meta:
        model = Charger

Edit: As AKS pointed out, a serializer should be passed instance rather than data when serializing ( data is for deserializing), and you don't need to check .is_valid() 编辑:正如AKS所指出的,序列化时应将序列化器而不是data传递给instancedata用于反序列化),并且您不需要检查.is_valid()

you are passing the keyword data when creating the serializer instance, witch is only used when deserializing data. 您在创建序列化程序实例时传递关键字数据,仅当反序列化数据时才使用witch。 you should create the DeviceSerializer with an object with the fields you want. 您应该使用带有所需字段的对象创建DeviceSerializer。 I haven't tested, but maybe something like this 我还没有测试过,但也许像这样

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 Django Rest 框架中使用 SerializerMethodField 进行更新 - How to update with SerializerMethodField in Django Rest Framework 在Django rest_framework中结合SerializerMethodField和DateField - Combine SerializerMethodField and DateField in django rest_framework Django Rest Framework 如何更新 SerializerMethodField - Django Rest Framework How to update SerializerMethodField Django REST 框架:指定SerializerMethodField的数据类型 - Django REST Framework: Specify data type of SerializerMethodField Django Rest Framework SerializerMethodField 传递额外参数 - Django Rest Framework SerializerMethodField Pass Extra Argument Django Rest 框架在 SerializerMethodField 上的嵌套关系性能 - Django Rest Framework nested relationship performance on SerializerMethodField Django Rest 框架 - 减少查询并提高 SerializerMethodField() 的性能 - Django Rest Framework - reduce queries and increase performance for SerializerMethodField() django-rest-framework 动态添加 SerializerMethodField 到 Serializer - django-rest-framework add SerializerMethodField to Serializer dynamically 如何在 SerializerMethodField() 使用多个查询集优化 django-rest-framework 序列化程序 - How to optimize django-rest-framework serializers with multiple queryset at SerializerMethodField() Django Rest Framework序列化字典 - Django rest framework serialize a dictionary
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM