pythondjangodjango-views

Single view for multiple paths via URL kwargs


I'm building a simple API listing various plants. Currently, it's limited to filter via a single field like common name, species, etc.

My urls.py

urlpatterns = [
    path('project/family=<str:family>/', views.SpeciesDetail_family.as_view(), name='family'),
    path('project/species=<str:species>/', views.SpeciesDetail_species.as_view(), name='species')
]

And views.py

class SpeciesDetail_species(generics.ListAPIView):
    serializer_class = SpeciesSerializer

    def get_queryset(self):
        queryset = Species.objects.filter()
        species = self.kwargs['species']
        if species is not None:
            queryset = queryset.filter(species__iexact=species)
        return queryset

class SpeciesDetail_family(generics.ListAPIView):
    serializer_class = SpeciesSerializer

    def get_queryset(self):
        queryset = Species.objects.all()
        family = self.kwargs['family']
        if family is not None:
            queryset = queryset.filter(family__iexact=family)
        return queryset

How can I create a single view for these two paths? So, I just need to parameterize the lookup field (can be family, species, etc.) from the URL like /project/species=PlantSpecies/ or /project/family=PlantFamily/.

If I add kwargs to the path like path('project/family=<str:family>/', views.SpeciesDetail_family.as_view(), {'lu_field':'family'}, name='family'), how can I access lu_field in the views?


Solution

  • Take a look at the code below see if it works the way you want :

    from rest_framework import generics
    from .models import Species
    from .serializers import SpeciesSerializer
    
    class SpeciesDetail(generics.ListAPIView):
        serializer_class = SpeciesSerializer
    
        def get_queryset(self):
            queryset = Species.objects.all()
            # Access dynamic lookup field and value from kwargs
            lu_field = self.kwargs.get('lu_field')
            lu_value = self.kwargs.get('lu_value')
    
            # Filter the queryset dynamically
            if lu_field and lu_value:
                filter_kwargs = {f"{lu_field}__iexact": lu_value}
                queryset = queryset.filter(**filter_kwargs)
    
            return queryset
    
    

    and here is the urls:

    from django.urls import path
    from . import views
    
    urlpatterns = [
        path('project/<str:lu_field>=<str:lu_value>/', views.SpeciesDetail.as_view(), name='species_detail'),
    ]