Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: Use URL parameter in serializer

My goal is to use a URL parameter as a variable in a function and output it in the serializer. But the following solution doesnt work. Anybody know why?

The URL looks like this: 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', ]

enter image description here

enter image description here

like image 804
ScienceNoob Avatar asked Oct 20 '25 15:10

ScienceNoob


2 Answers

We would be required to update the code at two places.

  1. DetailView in views.py.

In this, we are updating context to include data_from. (please note, we can also access this directly in the 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 in the 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']
   

Another approach would be to access the request object directly from the context of the serializer. By default, the serializer context contains the request object in it. To do so, just update the serializer as mentioned below

OsdSerializer in the 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']
   
like image 186
VJ Magar Avatar answered Oct 22 '25 04:10

VJ Magar


First you need to change from accessing the parameter from kwargs to request.GET instead.

If you have a url like this in django '/user/<int:user_id>' then you access through kwargs.

But if you send a url parameter, like this '/user/?user_id=1'. You access through the request object.

In your situation, I think rest_framework will send the request to the serializer automatically. So you can do something like this:

def get_alternate_name(self, obj):
    date_from = self.request.GET.get('from')
like image 36
Felix Eklöf Avatar answered Oct 22 '25 03:10

Felix Eklöf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!