Поиск url-параметров в drf

Я создаю конечную точку api/users/ с помощью Django REST framework, которая должна возвращать некоторые данные о пользователе по id. Все хорошо, но я хочу получить параметр поиска для моей модели User из параметров url. Есть lookup_field и lookup_url_kwarg атрибуты GenericAPIView, но они, похоже, здесь бесполезны, потому что работают с параметрами, указанными в URLConf, если я правильно понял. Итак, мой вопрос заключается в том, как получить объект из базы данных, когда я перехожу к примеру /api/users?uid=123?

Мы, конечно, можем переопределить get_object() или get_queryset() или любую другую вещь, например, так:

class UserAPIView(RetrieveUpdateDestroyAPIView,
                  CreateAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()

    def get_object(self) -> User:
        uid = self.request.query_params.get('uid', None)

        if uid is None or not uid.isdigit():
            raise Http404

        self.kwargs.update({self.lookup_field: int(uid)})

        return super().get_object()

Но это выглядит довольно уродливо, не так ли? Я считаю, что должен быть лучший способ справиться с этим...

но здесь они, похоже, бесполезны, потому что работают с параметрами, указанными в URLconf, если я правильно понимаю.

Все верно, хотя фреймворк Django REST на самом деле учитывает строку запроса. Это для формата (JSON, CSV и т.д.), фильтрации, упорядочивания, поиска и разбивки на страницы. Но главная причина в том, что это необязательные параметры.

но это выглядит довольно некрасиво, не так ли? Я считаю, что должен быть лучший способ справиться с этим.

Вы могли бы поработать с небольшой смесью:

class PassQueryToKwarg:
    query_to_kwarg = None

    def dispatch(self, request, *args, **kwargs):
        query_to_kwargs = self.query_to_kwargs
        if isinstance(query_to_kwargs, None):
            query_to_kwargs = ()
        elif not isinstance(query_to_kwargs, (list, tuple)):
            query_to_kwargs = (query_to_kwargs,)
        for qtk in query_to_kwargs:
            v = request.query_params.get(qtk, None)
            if v is not None:
                kwargs[qtk] = v
        return super().dispatch(self, request, *args, **kwargs)

и затем, таким образом, смешайте его с:

class UserAPIView(PassQueryToKwarg, RetrieveUpdateDestroyAPIView, CreateAPIView):
    serializer_class = UserSerializer
    queryset = User.objects.all()
    query_to_kwarg = GenericAPIView.lookup_field

и это все.

Но на самом деле строки запросов для обязательных параметров - это просто неправильно. Действительно, тот факт, что эти параметры отображаются в пути, имеет вескую причину: Django соответствует пути, так что это означает, что он будет запускать представление только в том случае, если параметр там есть. Таким образом, это на самом деле делает логику более элегантной. Поэтому использование ее в качестве ?uuid=… только создает дополнительные проблемы. Как правило, указывайте обязательные параметры в пути, а необязательные - в строке запроса.

Хотя, возможно, это было не так, как задумано фреймворком Django REST, вероятно, лучше , а не искать в строке запроса первичный ключ извлекаемого объекта. Тем более, что это затрудняет устранение неоднозначности между извлечением списка элементов и извлечением отдельного элемента.

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