Home > Enterprise >  Django - How to register route with query parameters?
Django - How to register route with query parameters?

Time:12-30

Im very new to Django, struggling to find the answer Im looking for. Please bear with me.

In my app/urls.py file I have

router = routers.DefaultRouter()
router.register(r'drugs', views.DrugViewSet)

In my views.py file I have

class DrugViewSet(viewsets.ModelViewSet):
    queryset = Drug.objects.all().order_by('name')
    serializer_class = DrugSerializer

And my DrugSerializer class looks like

class DrugSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Drug
        fields = ('id', 'name', 'description', 'recommended_dose_mg', 'count', 'create_date', 'update_date')

So when I do a GET on /drugs, I correctly get the list of drugs. And when I take a UUID (primary key) on a specific drug and do a GET on /drugs/<primary_key>, it correctly pulls the specific drug.

However, I want the GET on /drugs/<primary_key> to display different data. I want to join it with another model that I have and return a new json response. How exactly would I do this?

CodePudding user response:

You can use Nested Serializer

For example, the following serializer:

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

Would serialize to a nested representation like this:

{
    'album_name': 'The Grey Album',
    'artist': 'Danger Mouse',
    'tracks': [
        {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
        {'order': 2, 'title': 'What More Can I Say', 'duration': 264},
        {'order': 3, 'title': 'Encore', 'duration': 159},
        ...
    ],
}

CodePudding user response:

Lookup field

There is a field in ViewSet called lookup_field. It actually defines a field of the model to use in such query variable.

So you can do this:

class DrugViewSet(viewsets.ModelViewSet):
    queryset = Drug.objects.all().order_by('name')
    serializer_class = DrugSerializer
    lookup_field = 'id'

Here is the link of the documentation: https://www.django-rest-framework.org/api-guide/generic-views/#attributes

But actually it is generated automatically for retrieve action in ViewSet and id is used. You can install some of swagger plugins to see it. For example:

Different serializers

If you want to set different serializers for different actions you can override a model of the ViewSet called get_serializer_class:

class DrugViewSet(viewsets.ModelViewSet):
    queryset = Drug.objects.all().order_by('name')
    serializer_class = DrugSerializer

    def get_serializer_class(self):
         if self.action == 'detail': 
              return DrugDetailSerializer
         return DrugSerializer

Documentation here: https://www.django-rest-framework.org/api-guide/generic-views/#get_serializer_classself

In the DrugDetailSerializer you can specify what data to serialize when GET /drug/<primary_key> field is called.

  • Related