当我尝试使用自定义过滤器时,它一直在本地开发中正常工作,但是当我们部署到生产环境(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视图
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)
这是我们的CustomFilter
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']
这是我们用于此项目的Package的版本
Django==1.10.8
djangorestframework==3.6.4
django-filter==1.0.4
djangorestframework-filters==0.10.2
答案 0 :(得分:1)
在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
这是个快速电话,但是我认为您的查询集不会在每个请求上都进行重新评估。 看看下面的评论:#确保对每个请求重新评估查询集。