Multiple lookup_fields for django rest framework

I have several APIs that historically work using id as a search field:

 /api/organization/10 

I have an interface that uses these api.

I am creating a new interface, and for some reason I would like to use slug instead of id:

 /api/organization/my-orga 

The API is built with the Django Rest Framework. In addition to changing the search field, api behavior should remain unchanged.

Is there a solution that allows my API to work with both slug and pk ? These two ways should give them the same results:

 /api/organization/10 /api/organization/my-orga 

Here is my API definition:

 # urls.py router = DefaultRouter() router.register(r'organization', Organization) urlpatterns = router.urls #view.py class Organization(viewsets.ModelViewSet): queryset = OrganisationGroup.objects.all() serializer_class = OrganizationSerializer # serializer.py class OrganizationSerializer(PermissionsSerializer): class Meta: model = Organization 

Thanks for your help.

+6
source share
3 answers

try it

 from django.db.models import Q import operator class MultipleFieldLookupMixin(object): def get_object(self): queryset = self.get_queryset() # Get the base queryset queryset = self.filter_queryset(queryset) # Apply any filter backends filter = {} for field in self.lookup_fields: filter[field] = self.kwargs[field] q = reduce(operator.or_, (Q(x) for x in filter.items())) return get_object_or_404(queryset, q) 

Then in view

 class Organization(MultipleFieldLookupMixin, viewsets.ModelViewSet): queryset = OrganisationGroup.objects.all() serializer_class = OrganizationSerializer lookup_fields = ('pk', 'another field') 

Hope this helps.

+6
source

 class MultipleFieldLookupMixin(object): """ Apply this mixin to any view or viewset to get multiple field filtering based on a `lookup_fields` attribute, instead of the default single field filtering. """ def get_object(self): queryset = self.get_queryset() # Get the base queryset queryset = self.filter_queryset(queryset) filter = {} for field in self.lookup_fields: if self.kwargs[field]: # Ignore empty fields. filter[field] = self.kwargs[field] return get_object_or_404(queryset, **filter) # Lookup the object class RetrieveUserView(MultipleFieldLookupMixin, generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer lookup_fields = ('account', 'username') 
0
source

I think the main answer is that this will not be a good REST / API design and simply will not be allowed by DRF.

0
source

All Articles