3

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.

Muhammad Naufil
  • 2,420
  • 2
  • 17
  • 48
  • What happens if you keep `lookup_fields = ["device", "start_time"]` but use `router.register(r''`? – Brian Destura Jul 27 '21 at 01:39
  • @bdbd to change the last slug, which is "pk", we not only need to add `kwargs_url` dictionary with `lookup_field` but also need to add exactly same `lookup_field` in views. That's why I changed `lookup_fields` in views with `lookup_field` and changed its value to `startup_time`. If they don't match, the URL remains as it is: `mydomain.com/viewset///organization//` If I add `lookup_fields` in `extra_kwargs` like, `extra_kwargs = { 'url': {'lookup_fields': ['device', 'start_time']}}` it doesn't work either and URL remains as above mentioned – Muhammad Naufil Jul 27 '21 at 06:13
  • Can you add the `MultipleFieldLookupMixin` definition? Also this sounds like perfect use case for custom router implementation. https://www.django-rest-framework.org/api-guide/routers/#custom-routers – MjZac Aug 10 '21 at 14:28
  • Please show the code for **`OrganizationModelViewSet`** – Lord Elrond Aug 16 '21 at 18:28

1 Answers1

1

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

Sabil
  • 3,750
  • 1
  • 5
  • 16