Поиск 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, вероятно, лучше , а не искать в строке запроса первичный ключ извлекаемого объекта. Тем более, что это затрудняет устранение неоднозначности между извлечением списка элементов и извлечением отдельного элемента.