DjangoRestFramework,如何向序列化器添加不来自模型的可选字段

huangapple go评论78阅读模式
英文:

DjangoRestFramework, how to add optional field not coming from model to serializer

问题

  1. class CamperSerializer(serializers.ModelSerializer):
  2. camper_id = serializers.IntegerField(source='id')
  3. weather = serializers.SerializerMethodField('get_weather', read_only=True)
  4. def get_weather(self, instance):
  5. # Add your logic to fetch weather here
  6. lat = instance.location.y
  7. lon = instance.location.x
  8. return getWeatherFromLatLon(lat, lon)
  9. class Meta:
  10. model = Camper
  11. fields = ('camper_id', 'name', 'location', 'weather')
英文:

I have a model like this:

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

and a viewset like this:

  1. class CamperViewSet(viewsets.ModelViewSet):
  2. ...
  3. def retrieve(self, request, *args, **kwargs):
  4. """Retrieve a Camper instance."""
  5. show_weather = request.query_params.get('showWeather', False)
  6. instance = self.get_object()
  7. if show_weather:
  8. lat = instance.location.y
  9. lon = instance.location.x
  10. instance.weather = getWeatherFromLatLon(lat, lon)
  11. serializer = self.get_serializer(instance)
  12. return Response(serializer.data)

So when I request /api/campers/8?showWeather=true I make another request in my view to get the weather from the current position.

How do I add it to my serializer ? It's an optional field so I need to manage this and it's only used in /campers/id so it will not be used in list/create/put/etc

My serializer looks like this:

  1. class CamperSerializer(serializers.ModelSerializer):
  2. camper_id = serializers.IntegerField(source='id')
  3. class Meta:
  4. model = Camper
  5. fields = ('camper_id', 'name', 'location')
  6. </details>
  7. # 答案1
  8. **得分**: 1
  9. 你可以为`retrive`操作添加`custom serializer`。我称之为`CamperRetriveSerializer`
  10. `CamperRetriveSerializer`内,你可以使用`SerializerMethodField`来定义数据库中不存在的字段。
  11. 并且,你想要检查请求中的参数`show_weather`,最好是将其值传递到`context`中,并在序列化器中获取它。
  12. 像这样:
  13. ```python
  14. class CamperRetriveSerializer(serializers.ModelSerializer):
  15. weather = serializers.SerializerMethodField()
  16. camper_id = serializers.IntegerField(source='id')
  17. def get_weather(self, obj):
  18. show_weather = self.context.get('show_weather')
  19. if show_weather:
  20. lat = obj.location.y
  21. lon = obj.location.x
  22. return getWeatherFromLatLon(lat, lon)
  23. # 如果在请求中没有show_weather,则定义默认值
  24. return ''
  25. class Meta:
  26. model = Camper
  27. fields = ('camper_id', 'name', 'location', 'weather')
  28. class CamperViewSet(viewsets.ModelViewSet):
  29. ...
  30. def retrieve(self, request, *args, **kwargs):
  31. """Retrieve a Camper instance."""
  32. instance = self.get_object()
  33. show_weather = self.request.query_params.get('showWeather', False)
  34. context = {
  35. 'show_weather': show_weather
  36. }
  37. serializer = CamperRetriveSerializer(instance, context=context)
  38. return Response(serializer.data)
英文:

you can add custom serializer for retrive only todo it. I called CamperRetriveSerializer.

Inside CamperRetriveSerializer, you can use SerializerMethodField for define field not have in database.

And you want check param show_weather from request, best is pass value of it to context and get it in serializer.

Like this:

  1. class CamperRetriveSerializer(serializers.ModelSerializer):
  2. weather = serializers.SerializerMethodField()
  3. camper_id = serializers.IntegerField(source=&#39;id&#39;)
  4. def get_weather(self, obj):
  5. show_weather = self.context.get(&#39;show_weather&#39;)
  6. if show_weather:
  7. lat = obj.location.y
  8. lon = obj.location.x
  9. return getWeatherFromLatLon(lat, lon)
  10. # define default value if not show_weather in this
  11. return &#39;&#39;
  12. class Meta:
  13. model = Camper
  14. fields = (&#39;camper_id&#39;, &#39;name&#39;, &#39;location&#39;, &#39;weather&#39;)
  15. class CamperViewSet(viewsets.ModelViewSet):
  16. ...
  17. def retrieve(self, request, *args, **kwargs):
  18. &quot;&quot;&quot;Retrieve a Camper instance.&quot;&quot;&quot;
  19. instance = self.get_object()
  20. show_weather = self.request.query_params.get(&#39;showWeather&#39;, False)
  21. context = {
  22. &#39;show_weather&#39;: show_weather
  23. }
  24. serializer = CamperRetriveSerializer(instance, context=context)
  25. return Response(serializer.data)

答案2

得分: 0

你可以为此使用两种不同的序列化器。

  1. class CamperViewSet(viewsets.ModelViewSet):
  2. serializer_class = CamperSerializer
  3. def get_serializer_class(self):
  4. serializer_class = self.serialzier_class
  5. if self.request.method == &#39;GET&#39;:
  6. serializer_class = CamperSerializerGet
  7. return serializer_class
  8. # 用于GET请求的序列化器
  9. class CamperSerializerGet(serializers.ModelSerializer):
  10. weather = serialziers.SerializerMethodField()
  11. camper_id = serializers.IntegerField(source=&#39;id&#39;)
  12. def get_weather(self, obj):
  13. return obj.weather
  14. class Meta:
  15. model = Camper
  16. fields = (&#39;camper_id&#39;, &#39;name&#39;, &#39;location&#39;, &#39;weather&#39;)
  17. # 用于其他请求的序列化器
  18. class CamperSerializer(serializers.ModelSerializer):
  19. camper_id = serializers.IntegerField(source=&#39;id&#39;)
  20. class Meta:
  21. model = Camper
  22. fields = (&#39;camper_id&#39;, &#39;name&#39;, &#39;location&#39;)
英文:

You can use two different serializers for this.

  1. class CamperViewSet(viewsets.ModelViewSet):
  2. serializer_class = CamperSerializer
  3. def get_serializer_class(self):
  4. serializer_class = self.serialzier_class
  5. if self.request.method == &#39;GET&#39;:
  6. serializer_class = CamperSerializerGet
  7. return serializer_class
  8. #Serializer for GET request
  9. class CamperSerializerGet(serializers.ModelSerializer):
  10. weather = serialziers.SerializerMethodField()
  11. camper_id = serializers.IntegerField(source=&#39;id&#39;)
  12. def get_weather(self, obj):
  13. return obj.weather
  14. class Meta:
  15. model = Camper
  16. fields = (&#39;camper_id&#39;, &#39;name&#39;, &#39;location&#39;, &#39;weather&#39;)
  17. #For other requests call this
  18. class CamperSerializer(serializers.ModelSerializer):
  19. camper_id = serializers.IntegerField(source=&#39;id&#39;)
  20. class Meta:
  21. model = Camper
  22. fields = (&#39;camper_id&#39;, &#39;name&#39;, &#39;location&#39;)

huangapple
  • 本文由 发表于 2023年2月14日 02:15:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75439749.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定