Multiple lookup_fields for django rest framework

后端 未结 8 573
你的背包
你的背包 2020-12-10 03:30

I have multiple API which historically work using id as the lookup field:

/api/organization/10

I have a frontend consuming tho

8条回答
  •  渐次进展
    2020-12-10 04:22

    There are a lot of answers here already, but none provide a full description including the mixin, view, and url configuration. This answer does.

    This is the mixin that works best, it is slightly modified from https://www.django-rest-framework.org/api-guide/generic-views/#creating-custom-mixins to not error out on non-existing fields.

    class MultipleFieldLookupMixin:
        """
        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.
    
        Source: https://www.django-rest-framework.org/api-guide/generic-views/#creating-custom-mixins
        Modified to not error out for not providing all fields in the url.
        """
    
        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:
                if self.kwargs.get(field):  # Ignore empty fields.
                    filter[field] = self.kwargs[field]
            obj = get_object_or_404(queryset, **filter)  # Lookup the object
            self.check_object_permissions(self.request, obj)
            return obj
    

    Now add the view as follows, it is important to have the Mixin first, otherwise the get_object method is not overwritten:

    class RudAPIView(MultipleFieldLookupMixin, generics.RetrieveUpdateDestroyAPIView):
        ...
        lookup_fields = ['pk', 'other_field']
    

    Now, for the urls, we use default converters. It is important int comes first as that one will actually check if it is an int, and if not fallback to str. If you have more complex fields, you need to resort to regex.

    path('efficiency//', views.RudAPIView.as_view(), name='something-rud'),
    path('efficiency//', views.RudAPIView.as_view(), name='something-rud'),
    

提交回复
热议问题