Django Rest Framework:在序列化程序中使用 URL 参数

Django Rest Framework: Use URL parameter in serializer

我的目标是使用 URL 参数作为函数中的变量,并在序列化程序中输出它。但以下解决方案不起作用。有人知道为什么吗?

URL 看起来像这样: http://127.0.0.1:8000/v1/water-bodies/?from=2013-02-17&to=2013-02-18

models.py

class Application(models.Model):
    """Database models for application information"""

    name = models.CharField(max_length=255)
    machine_name = models.SlugField(max_length=255, allow_unicode=True)
    description = models.TextField(blank=True, null=True)
    indice_to_use = models.ForeignKey('Indice', on_delete=models.PROTECT, blank=True, null=True)

    def __str__(self):
        return self.name

views.py

class DetailView(APIView):
    def get_serializer_context(self):
        context = super().get_serializer_context()
        context["date_from"] = self.request.query_params.get("from", None)
        return context

    def get(self, request, machine_name):
        application = Application.objects.get(machine_name=machine_name)
        serializer = OsdSerializer(application)

        return Response({"Everything you need to analyzing "+application.name: serializer.data})

serializer.py

class OsdSerializer(serializers.ModelSerializer):
    bands = BandSerializer(source='indice_to_use.needed_bands', many=True)
    satellite = SatelliteSerializer(source='indice_to_use.satellite_to_use')
    indice = IndiceSerializer(source='indice_to_use')

    def get_alternate_name(self, obj):
        return self.context.get('date_from')

    class Meta:
        model = Application
        fields = ['machine_name', 'name', 'description', 'indice', 'satellite', 'bands', 'date_from', ]

首先,您需要将访问参数从 kwargs 更改为 request.GET

如果你在 django '/user/<int:user_id>' 中有这样的 url 那么你可以通过 kwargs 访问。

但是如果你发送一个url参数,像这样'/user/?user_id=1'。您通过请求对象访问。

在你的情况下,我认为 rest_framework 会自动将请求发送到序列化程序。所以你可以这样做:

def get_alternate_name(self, obj):
    date_from = self.request.GET.get('from')

我们需要在两个地方更新代码。

  1. views.py 中的详细视图。

在此,我们正在更新上下文以包含 data_from。 (请注意,我们也可以直接在 serialzier 中访问它)

class DetailView(APIView):
 ...
    def get(self, request, machine_name):
        application = Application.objects.get(machine_name=machine_name)
        serializer = OsdSerializer(application, context={
           "date_from": request.query_params.get("from")
        })

        return Response({"Everything you need to analyzing "+application.name: serializer.data})
 ...
  1. OsdSerializer 在 serializers.py
class OsdSerializer(serializers.ModelSerializer):

   bands = BandSerializer(source='indice_to_use.needed_bands', many=True)
   satellite = SatelliteSerializer(source='indice_to_use.satellite_to_use')
   indice = IndiceSerializer(source='indice_to_use')
   alternate_name = serializers.SerializerMethodField()   

   def get_alternate_name(self, obj):
        return self.context.get('date_from')

   class Meta:
        model = Application
        fields = ['machine_name', 'name', 'description', 'indice', 'satellite', 'bands', 'date_from', 'alternate_name']
   

另一种方法是直接从序列化程序的上下文中访问请求对象。默认情况下,序列化程序上下文中包含请求对象。为此,只需按以下所述更新序列化程序

OsdSerializer 在 serializers.py

class OsdSerializer(serializers.ModelSerializer):

   bands = BandSerializer(source='indice_to_use.needed_bands', many=True)
   satellite = SatelliteSerializer(source='indice_to_use.satellite_to_use')
   indice = IndiceSerializer(source='indice_to_use')
   alternate_name = serializers.SerializerMethodField()   

   def get_alternate_name(self, obj):
        return self.context.get('request').query_params.get('from', None)
  
   class Meta:
        model = Application
        fields = ['machine_name', 'name', 'description', 'indice', 'satellite', 'bands', 'date_from', 'alternate_name']