Django Rest Framework 在结果中随机返回空列表,但计数仍然正确

标签 django django-rest-framework django-filter django-rest-framework-filters

当我尝试使用自定义过滤器时,它在本地开发中一直在工作,但是当我们部署到生产(Docker Swarm)时,我们发现一个问题,有时 API 响应随机返回空结果,但计数为正确的。以下是 API 的示例结果

API响应

{
    'count': 1, 
    'next': 'http://localhost:8000/api/somethings/?email=test%40example.com&limit=0&offset=0', 
    'previous': None, 
    'results': []
}

现在我们需要重新启动一个uwsgi服务(通过重新启动该服务的docker swarm),问题暂时解决了,然后又随机发生。

这是我们的 DRF View

class SomeView(ListCreateAPIView):
    queryset = SomeModel.objects.all()
    serializer_class = SomeModelSerializer
    filter_backends = (OrderingFilter, DjangoFilterBackend)
    filter_class = CustomFilter
    ordering = ('id',)

    def list(self, request, *args, **kwargs):
        if request.GET.get('all', None):
            # Do something
            serializer = self.get_serializer(queryset, many=True)
            return Response(serializer.data)
        else:
            return super(SomeView, self).list(self, request, *args, **kwargs)

这是我们的自定义过滤器

from django_filters.rest_framework.filters import CharFilter
import rest_framework_filters as filters


class CustomFilter(filters.FilterSet):
    json_field_separator = '___'

    json_field_is = CharFilter(name='json_field', method='filter_json_field')
    json_field_is_not = CharFilter(name='json_field', method='exclude_json_field')

    def split_lookup_field(self, value):
        return dict(field.split(':') for field in value.split(self.json_field_separator))

    def filter_json_field(self, queryset, name, value):
        try:
            lookup_field = self.split_lookup_field(value)
            return queryset.filter(**lookup_field)
        except (ValueError, FieldError):
            return queryset.none()

    def exclude_json_field(self, queryset, name, value):
        try:
            lookup_field = self.split_lookup_field(value)
        except (ValueError, FieldError):
            return queryset.none()

        for query_arg, query_value in lookup_field.items():
            queryset = queryset.exclude(**{query_arg: query_value})

        return queryset

    class Meta:
        model = SomeModel
        exclude = ['image', 'json_field']

这是我们用于此项目的包版本

Django==1.10.8
djangorestframework==3.6.4
django-filter==1.0.4
djangorestframework-filters==0.10.2

最佳答案

在 GenericAPIView 中,您可以找到一个名为:get_queryset() 的方法,如下所示:

def get_queryset(self):
    """
    Get the list of items for this view.
    This must be an iterable, and may be a queryset.
    Defaults to using `self.queryset`.

    This method should always be used rather than accessing `self.queryset`
    directly, as `self.queryset` gets evaluated only once, and those results
    are cached for all subsequent requests.

    You may want to override this if you need to provide different
    querysets depending on the incoming request.

    (Eg. return a list of items that is specific to the user)
    """
    assert self.queryset is not None, (
        "'%s' should either include a `queryset` attribute, "
        "or override the `get_queryset()` method."
        % self.__class__.__name__
    )

    queryset = self.queryset
    if isinstance(queryset, QuerySet):
        # Ensure queryset is re-evaluated on each request.
        queryset = queryset.all()
    return queryset

这是一个快速调用,但我认为您的查询集不会针对每个请求重新评估。 看一下这个评论:# Ensure queryset is re-evaluate on every request.

关于Django Rest Framework 在结果中随机返回空列表,但计数仍然正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52055584/

相关文章:

python - 没有名为 django_filters 的模块

python - 如何从值 models.IntegerChoices 中获取标签

django - 使用 elasticsearch-dsl DocType 映射配置

python - Django Rest Framework 使用 filterset_fields 在 ViewSet 中过滤计算出的 SerializerMethodField()

python - 使用 py_compile 时未捕获语法错误

python - 如何修改 django-rest-framework API

django - 如何在 DRF 中将 django filter_fields 与 ArrayField 一起使用

带换行符的字符串的Python格式

python - Django:如何在 list_display 中包含内联模型字段?

python - 使用 django-rest-interface