Django Rest Framework - Viewsets and overriding methods to allow multiple forms of the lookup value

Submitted 3 years, 7 months ago
Ticket #165
Views 297
Language/Framework Django
Priority Medium
Status Closed

I am new to DRF and I am having trouble with overriding its methods.

I would like to allow a Viewset to accept two different forms of the same lookup value, essentially a substring of the value and the full string.

Ex. location and the db pk, location.namespace.host.com

I was able to successfully override the get_object method to allow both values for a GET request, but if I try to submit a POST to update the status, then it doesn't work. Since it's a pk, it tries to create a new db entry with pk = location and fails.

It doesn't seem happy with me changing the kwarg (it reverts back to the old kwarg when running a csrf_exempt decorator function from the DRF library).

What is the proper way to do this?

from rest_framework import serializers
from myapp.apps.clusters.models import Status
from myapp.com.mixins.ViewSets import CreateUpdateListRetrieveViewSet
from django.http import Http404
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import UpdateModelMixin


class StatusSerializer(serializers.ModelSerializer):
    class Meta:
        model = Status
        lookup_field = 'hostname'


class StatusViewSet(CreateUpdateListRetrieveViewSet):
    model = Status
    serializer_class = StatusSerializer
    lookup_field = 'hostname'

    def get_object(self, queryset=None):
        """
        Overrides the GenericView method to allow for both hostname and physname lookups

        i.e. physname (location) or full FQDN (location.namespace.host.com)
Returns the object the view is displaying.
        """
        try:
            obj = GenericAPIView.get_object(self)
        except Http404:
            hostname = self.kwargs.get(self.lookup_field, None) + '.namespace.host.com'
            self.kwargs[self.lookup_field] = hostname
            obj = GenericAPIView.get_object(self)    
        return obj

    def update(self, request, *args, **kwargs):
        """ This doesn't play nice, overriding UpdateModelMixin's update """
        lookup_field = self.kwargs.get(self.lookup_field, None)
        if not '.namespace.host.com' in lookup_field
            hostname = lookup_field + '.namespace.host.com'
            self.kwargs['hostname'] = hostname
            kwargs['hostname'] = hostname
        return UpdateModelMixin.update(self, request, *args, **kwargs)

    def pre_save(self, obj):
        """ This was an attempt but the code is not currently hit """
        if not '.namespace.host.com' in self.kwargs['hostname']:
 self.kwargs['hostname'] = self.kwargs['hostname'] + '.namespace.host.com'

Thank you for any help!

Submitted on Sep 13, 20
add a comment

1 Answer

Verified

Override your get_serializer_class method. This method is used in your model mixins to retrieve the proper Serializer class.

There is also a get_serializer method which returns an instance of the correct Serializer

class DualSerializerViewSet(viewsets.ModelViewSet):
    def get_serializer_class(self):
        if self.action == 'list':
            return serializers.ListaGruppi
        if self.action == 'retrieve':
            return serializers.DettaglioGruppi
        return serializers.Default # I dont' know what you want for create/destroy/update. 

Submitted 3 years, 6 months ago


Latest Blogs