Django的REST框架 - 过滤(Django REST Framework - Filteri

2019-07-18 02:06发布

我想筛选与多个查询像这样多个字段:

api/listings/?subburb=Subburb1, Subburb2&property_type=House,Apartment,Townhouse,Farm .. etc

是否有任何内置的方式,我看了一下Django的过滤器,但它似乎有限,我想我会在我的API视图中手动做到这一点,但它越来越凌乱,在过滤器过滤的过滤器

Answer 1:

在过滤器上过滤上的过滤器不凌乱它被称为chained filters

而链过滤器,因为那里的某个时候将是必要property_type有一段时间没有:

if property_type:
    qs = qs.filter(property_type=property_type)

如果你正在考虑那里将是多个查询则不是,它仍然会在一个查询,因为查询集是懒惰的执行。

另外,您可以建立一个字典,并通过它只是一个时间:

d = {'property_type:': property_type, 'subburb': subburb}
qs = MyModel.objects.filter(**d)


Answer 2:

复杂的过滤器不出来的DRF甚至通过Django的过滤器插件支持的盒子。 对于简单的情况下,你可以定义自己的get_queryset方法

这是直接从文档

def get_queryset(self):
    queryset = Purchase.objects.all()
    username = self.request.query_params.get('username', None)
    if username is not None:
        queryset = queryset.filter(purchaser__username=username)
    return queryset

然而,如果你支持多个过滤器,甚至他们中的一些复杂的这很快就会变得杂乱。

解决的办法是定义一个自定义filterBackend类和视图集的Mixin。 这混入告诉视图集中如何了解一个典型的过滤器后端,这后端可以理解非常复杂的过滤器都明确定义,包括规则时应该应用这些过滤器。

样品过滤器后端是这样的(我已经定义在复杂性增大的顺序不同的查询参数三个不同的过滤器:

class SomeFiltersBackend(FiltersBackendBase):
    """
    Filter backend class to compliment GenericFilterMixin from utils/mixin.
    """
    mapping = {'owner': 'filter_by_owner',
               'catness': 'filter_by_catness',
               'context': 'filter_by_context'}
    def rule(self):
        return resolve(self.request.path_info).url_name == 'pet-owners-list'

对ORM查找直线前进的过滤器。

    def filter_by_catness(self, value):
        """
        A simple filter to display owners of pets with high catness, canines excuse. 
        """
        catness = self.request.query_params.get('catness')
        return Q(owner__pet__catness__gt=catness)

    def filter_by_owner(self, value):
        if value == 'me':
            return Q(owner=self.request.user.profile)
        elif value.isdigit():
            try:
                profile = PetOwnerProfile.objects.get(user__id=value)
            except PetOwnerProfile.DoesNotExist:
                raise ValidationError('Owner does not exist')
            return Q(owner=profile)
        else:
            raise ValidationError('Wrong filter applied with owner')

更复杂的过滤器:

def filter_by_context(self, value):
    """
    value = {"context_type" : "context_id or context_ids separated by comma"}
    """
    import json
    try:
        context = json.loads(value)
    except json.JSONDecodeError as e:
        raise ValidationError(e)

    context_type, context_ids = context.items()
    context_ids = [int(i) for i in context_ids]
    if context_type == 'default':
        ids = context_ids
    else:
        ids = Context.get_ids_by_unsupported_contexts(context_type, context_ids)
    else:
        raise ValidationError('Wrong context type found')
    return Q(context_id__in=ids)

要充分了解如何工作的,你可以阅读我的博客帖子详细: http://iank.it/pluggable-filters-for-django-rest-framework/

所有的代码有一个要点,以及: https://gist.github.com/ankitml/fc8f4cf30ff40e19eae6



文章来源: Django REST Framework - Filtering