Как указать пользовательское поле поиска для действия DRF в наборе представлений?
Я хотел бы указать пользовательское поле поиска в действии (отличное от поля по умолчанию viewset "pk"), т.е.
@action(
methods=["GET"],
detail=True,
url_name="something",
url_path="something",
lookup_field="uuid", # this does not work unfortunately
)
def get_something(self, request, uuid=None):
pass
Но маршрутизатор не генерирует правильные урлы:
router = DefaultRouter()
router.register(r"test", TestViewSet)
router.urls
выдает url:
'^test/(?P<pk>[^/.]+)/something/$'
вместо
'^test/(?P<uuid>[^/.]+)/something/$'
Я не хочу изменять поле поиска для всей модели, и мне не удалось найти способ сделать это для самого действия после отладки через генерацию url маршрутизатора. Я заметил, что наборы представлений модели имеют такой метод:
get_extra_action_url_map(Self)
но я не знаю, как заставить его вызываться для генерации пользовательских урлов и имеет ли он вообще значение. Любая помощь была бы очень кстати, спасибо!
Я думаю, что это создаст большую путаницу для потребителей вашего API, если у вас будет 2 разных идентификатора ресурса на одном и том же ресурсе.
Вы можете назвать это действие query_by_uuid
или просто позволить им использовать list_view
для фильтрации по uuid
, если вы хотите представлять только объект. (чтобы потребители могли использовать /test/?uuid= для получения данных)
Но если вы действительно хотите это сделать, вы можете просто переопределить метод get_object
для фильтрации вашего пользовательского действия tho:
def get_object(self):
if self.action == 'do_something':
return get_object_or_404(self.get_queryset(), uuid=self.kwargs['pk'])
return super().get_object()
Согласно их документации вы можете использовать поле поиска regex. В их примере используется CBV вместо представления на основе запроса.
class MyModelViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet):
lookup_field = 'uuid'
lookup_value_regex = '[0-9a-f]{32}'
Это может сработать:
@action(
methods=["GET"],
detail=True,
url_name="something",
url_path="something",
lookup_field = 'uuid'
lookup_value_regex = '[0-9a-f]{32}'
)
def get_something(self, request, uuid=None):
pass