Replace Default PK slug with Multiple Lookup Fields for ModelViewSet

629 Views Asked by At

I have two slugs, against which I run queries. Thanks to base class MultipleFieldLookupMixin, which my view class is inherited from and thus allows me to have multiple lookup_fields.

We know that when ModelViewSet is used with DefaultRouter, appends a pk at the end of URL, which I don't want.

For example, when I do this:

router = DefaultRouter()
router.register(r'organization', OrganizationModelViewSet, basename='organization')


urlpatterns = [
    path('viewset/<str:device>/<str:start_time>/', include(router.urls))
]

it gives me the URL

mydomain.com/viewset/<str:device>/<str:start_time>/organization/<int:pk>/

I don't want this pk at the end. If we can remove organization, that's even better. I want the endpoint to be,

mydomain.com/<str:device>/<str:start_time>/.

More playing around, I learned that adding extra_kwargs like this in my serializer class,

    extra_kwargs = {
        'url': {'lookup_field': 'start_time'}
    }

and modify lookup_fields in view class, with singular lookup field, like lookup_field, with value let's say, start_time, as shown

lookup_fields = ["device", "start_time"]

with

lookup_field = "start_time"

and also modify the URL accordingly by removing the start_time slug, then URL becomes

mydomain.com/viewset/<str:device>/organization/<str:start_time>/

Modifying singular lookup_field with start_time, apparently gives us more or less the desired URL, but doesn't get the job done because we have a single lookup_field now!

If we edit this line

router.register(r'organization', DeviceActivityModelViewSet, basename='device_activity')

to

router.register(r'', DeviceActivityModelViewSet, basename='device_activity')

then we get the URL

mydomain.com/viewset/<str:device>/<str:start_time>/

which is exactly what I want, but still as I said, it doesn't work, because of the single lookup field.

Cutting to the chase, I hope it clarifies my research into this and I restate my problem statement that I want to have this URL endpoint

mydomain.com/<str:device>/<str:start_time>/.

with two slugs, without changing the base class for my view i.e ModelViewSet. I know the functionality I want can be easily done with GenericAPIView and I also have done it, but I am curious how to do it this way.

1

There are 1 best solutions below

0
Sabil On

As i don't have to full view of your code so I think below code snippet should work for you.

urlpatterns = [
    path('/<str:device>/<str:start_time>/', include(router.urls))
]

If it didn't work then please let me know