Маршрутизация Django Rest Framework с префиксом первичного ключа

Я использую DRF DefaultRouter следующим образом.

# urls.py
router = DefaultRouter()
router.register('book', BookingViewSet, basename='booking')
router.register('book/<int:bk>/reservation', ReservationViewSet, basename='reservation')

urlpatterns = [
   path('', include(router.urls)),
]

# view
class ReservationViewSet(viewsets.ModelViewSet):
    serializer_class = ReservationSerializer
    queryset = Reservation.objects.all() # for testing only

Но когда я посещаю URL /book/1/reservation/, он говорит, что шаблон url не найден.

lending/ ^book/<int:bk>/reservation/$ [name='reservation-list']
lending/ ^book/<int:bk>/reservation\.(?P<format>[a-z0-9]+)/?$ [name='reservation-list']
lending/ ^book/<int:bk>/reservation/(?P<pk>[^/.]+)/$ [name='reservation-detail']
lending/ ^book/<int:bk>/reservation/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='reservation-detail'] 

The current path, lending/book/1/reservation/, didn’t match any of these. 

Я использую bk для захвата идентификатора книги.

Это потому, что он реализует <int:bk> как regex, поэтому без какой-либо интерпретации. Вероятно, проще всего это сделать с помощью двух маршрутизаторов:

router1 = DefaultRouter()
router1.register('book', BookingViewSet, basename='booking')

router2 = DefaultRouter()
router2.register('reservation', ReservationViewSet, basename='reservation')

urlpatterns = [
   path('', include(router1.urls)),
   path('book/<int:bk>/', include(router2.urls)),
]

В ReservationViewSet вы можете, например, фильтровать с помощью bk:

class ReservationViewSet(viewsets.ModelViewSet):
    serializer_class = ReservationSerializer

    def get_queryset(self):
        return Reservation.objects.filter(book_id=self.kwargs['bk'])

Просто хотел добавить это к принятому ответу ... Вы также можете сделать это с помощью того же маршрутизатора, просто вставьте pk в URL в форме regex, как предлагает сообщение об ошибке:

# urls.py
router = DefaultRouter()
router.register('book', BookingViewSet, basename='booking')
router.register('book/(?P<bk>[^/.]+)/reservation', ReservationViewSet, basename='reservation')

urlpatterns = [
   path('', include(router.urls)),
]

Затем вы можете получить доступ к аргументу bk в вашем представлении, используя self.kwargs['bk'].

Вернуться на верх