Django View Return Queryset с дополнительной информацией - PullRequest
0 голосов
/ 10 октября 2018

У меня нормальное представление Django, которое возвращает API для набора запросов.Он берет параметры запроса из URL и фильтрует базу данных на основе параметров.Он также выводит максимальную длину 3 объекта "Part".

Я хотел бы добавить что-то, чтобы он возвращал информацию о том, обрезан ли набор запросов максимальной длиной 3. Идея состоит в том, что, поскольку входные данныепараметры запроса, если параметры слишком расплывчаты, то из базы данных будет запрашиваться слишком много данных.Таким образом, оно обрезается, но затем пользователь должен знать, что оно было обрезано.

Текущий код выглядит следующим образом

class PartList(generics.ListAPIView):
serializer_class = PartSerializer

def get_queryset(self):
    """
    Optionally restricts the returned purchases to a given user,
    by filtering against a `username` query parameter in the URL.
    """
    queryset = Part.objects.all()

    querydict = self.request.query_params

    for (k, value) in querydict.items():
        search_type = 'contains'
        filter = k + '__' + search_type
        queryset = queryset.filter(**{filter: value})

    query_max_limit = 3
    return queryset[:min(len(queryset), query_max_limit)]

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Совершенно нормально передавать метаданные вместе с вашими результатами, например:

{ "is_clipped": true, "results": [ … ] }

Ответ Виллема - хороший способ установить is_clipped.

Но я думаю, что вы заинтересованы в нумерации страниц , которая является стандартным способом информирования клиентов о том, что результаты обрезаны.Возможно объединить вашу строку набора запросов с нумерацией страниц .Кстати, я предлагаю вам использовать django-filter вместо того, чтобы использовать собственную фильтрацию.

0 голосов
/ 10 октября 2018

Вы можете попытаться получить четыре элемента, и, если он вернет четыре, вы отобразите first three и укажите, что данные обрезаются, например:

def get_queryset(self):
    """
    Optionally restricts the returned purchases to a given user,
    by filtering against a `username` query parameter in the URL.
    """
    queryset = Part.objects.all()

    querydict = self.request.query_params

    for (k, value) in querydict.items():
        search_type = 'contains'
        filter = k + '__' + search_type
        queryset = queryset.filter(**{filter: value})

    query_max_limit = 3
    qs = queryset[:query_max_limit+1]
    self.clipped = clipped = len(qs) > query_max_limit
    if clipped:
        return list(qs)[:query_max_limit]
    else:
        return qs

Итак, get_queryset вернет коллекцию (не по сути QuerySet), содержащую максимум три элемента, и установит атрибут self.clipped, который определяет, будет лиданные были обрезаны.

Или более элегантный подход - сначала сосчитать, а затем срезать:

def get_queryset(self):
    """
    Optionally restricts the returned purchases to a given user,
    by filtering against a `username` query parameter in the URL.
    """
    queryset = Part.objects.all()

    querydict = self.request.query_params

    for (k, value) in querydict.items():
        search_type = 'contains'
        filter = k + '__' + search_type
        queryset = queryset.filter(**{filter: value})

    query_max_limit = 3
    qs = queryset[:query_max_limit+1]
    self.clipped = clipped = qs.count() > query_max_limit
    if clipped:
        return queryset[:query_max_limit]
    else:
        return qs

Возможно, было бы лучше переместить эту логику «отсечения» в выделенную функцию,и вернуть, если оно обрезано, вместо установки атрибута.

...