DjangoRestFramework,如何将非来自模型的可选字段添加到序列化器

h6my8fg2  于 2023-02-17  发布在  Go
关注(0)|答案(2)|浏览(128)

我有这样一个模型:

class Camper(models.Model):
    location = models.PointField()
    name = models.CharField(max_length=255)

和这样的视图集:

class CamperViewSet(viewsets.ModelViewSet):
...
    def retrieve(self, request, *args, **kwargs):
        """Retrieve a Camper instance."""
        show_weather = request.query_params.get('showWeather', False)
        instance = self.get_object()
        if show_weather:
            lat = instance.location.y
            lon = instance.location.x
            instance.weather = getWeatherFromLatLon(lat, lon)

        serializer = self.get_serializer(instance)
        return Response(serializer.data)

因此,当我请求/api/campers/8?showWeather=true时,我在视图中发出另一个请求,以获取当前位置的天气。
如何将它添加到我的序列化器中?这是一个可选字段,因此我需要管理它,并且它只在/campers/id中使用,因此不会在list/create/put/etc中使用
我的序列化器如下所示:

class CamperSerializer(serializers.ModelSerializer):

    camper_id = serializers.IntegerField(source='id')

    class Meta:
        model = Camper
        fields = ('camper_id', 'name', 'location')
qjp7pelc

qjp7pelc1#

你可以只为retrive添加custom serializer。我调用了CamperRetriveSerializer
CamperRetriveSerializer中,您可以使用SerializerMethodField定义数据库中没有的字段。
您希望检查请求中的参数show_weather,最好将其值传递给context,并在串行化器中获取。
就像这样:

class CamperRetriveSerializer(serializers.ModelSerializer):
    
        weather = serializers.SerializerMethodField()
        camper_id = serializers.IntegerField(source='id')
    
        def get_weather(self, obj):
            show_weather = self.context.get('show_weather')
            if show_weather:
                lat = obj.location.y
                lon = obj.location.x
                return getWeatherFromLatLon(lat, lon)
    
            # define default value if not show_weather in this
            return ''
    
        class Meta:
            model = Camper
            fields = ('camper_id', 'name', 'location', 'weather')
    
    
    
    class CamperViewSet(viewsets.ModelViewSet):
    ...
    
    
        def retrieve(self, request, *args, **kwargs):
            """Retrieve a Camper instance."""
            instance = self.get_object()
            show_weather = self.request.query_params.get('showWeather', False)
            context = {
                'show_weather': show_weather
            }
            serializer = CamperRetriveSerializer(instance, context=context)
            return Response(serializer.data)
kpbwa7wx

kpbwa7wx2#

您可以为此使用两个不同的序列化程序。

class CamperViewSet(viewsets.ModelViewSet):
    serializer_class = CamperSerializer

    def get_serializer_class(self):
        serializer_class = self.serialzier_class
        if self.request.method == 'GET':
            serializer_class = CamperSerializerGet
        return serializer_class

#Serializer for GET request
class CamperSerializerGet(serializers.ModelSerializer):
    weather = serialziers.SerializerMethodField()
    camper_id = serializers.IntegerField(source='id')

    def get_weather(self, obj):
        return obj.weather    

    class Meta:
        model = Camper
        fields = ('camper_id', 'name', 'location', 'weather')

#For other requests call this
class CamperSerializer(serializers.ModelSerializer):

    camper_id = serializers.IntegerField(source='id')

    class Meta:
        model = Camper
        fields = ('camper_id', 'name', 'location')

相关问题