Coder Social home page Coder Social logo

python-blog's People

Watchers

 avatar

python-blog's Issues

drf rest过滤方法总结

传统的过滤方法

    User.object.filter(name='xxx')

url过滤

    path('<str:name>/vote/', vote_list, name='vote_list')
    ......
    class ListExample(mixins.ListModelMixin):
        serializer_class = UserSerializers
    
        def get_querySet(self):
            nm = self.kwarg['name']
            return User.object.filter(name=nm)

url查询参数过滤

    http://example.com/api/user?name=xxx
    ......
    param = self.request.query_params('name', None)
    querySet = User.object.filter(name=params)

Django-Filter过滤

简单过滤

setting.py中设置如下:

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
}

view.py代码:

    filter_backends = (DjangoFilterBackend,)
    filter_fields = ['name']

若是在admin中需要使用,安装django-crispy-forms

filterSet过滤

有时,简单的过滤方式无法实现我们的业务要求,需要自己定义过滤方法

class RangeWidget(DateRangeWidget):
    suffixes = ['from', 'to']

class FormFilter(django_filters.rest_framework.FilterSet):
    name = django_filters.CharFilter(field_name='game__name', lookup_expr='icontains')
    source = django_filters.CharFilter(field_name='game__source', lookup_expr='icontains')
    num = django_filters.NumberFilter(field_name='num', lookup_expr='gte')
    time = django_filters.DateFilter(field_name='pub_time')
    range = django_filters.DateTimeFromToRangeFilter(field_name='pub_time', widget=RangeWidget)

    class Meta:
        models = Post
        fields = ['name', 'source', 'num', 'pub_time', 'pub_time']
        
class PostView(mixins.ListModelMixin, GenericViewSet):
    """
        list:
            post列表
    """
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    pagination_class = PostPagination
    filter_backends = (DjangoFilterBackend,)
    filter_class = FormFilter

这里需要查看django-filter的文档

一般字符和数字的过滤很简单

过滤关键字
  • field_name:模型字段名称,外键关联字段可以通过双下划线(__)方式获取;
  • look_exrp:执行字段查找的方式,和django中的字段查找方法一样

此外还有method、lable、**kwarg、widget、distinct和exclude
详细参考相关文档

过滤器

除CharFilter和NumberFilter之外,还有很多如BooleanFilter、ChoiceFilter、DateFilter、TimeFilter、DateTimeFilter等

以上基本都是精准匹配,若是对于范围匹配,需要使用如下过滤器:
RangeFilter、DateRangeFilter、DateFromToRangeFilter、DateTimeFromToRangeFilter

以上代码有使用的方式,若是使用range类型的话,默认是在字段后匹配0和1

GET /products?price_0=10&price_1=25 HTTP/1.1

我们可以自己设置后缀,这里就要使用到小部件RangeWidget

from django_filters.widgets import SuffixedMultiWidget

class RangeWidget(SuffixedMultiWidget):
    suffixes = ['min', 'max']
    
class FormFilter(FilterSet):
    range = django_filters.RangeFilter(field_name='name', widget=RangeWidget)

    class Meta:
        fields = ['name']

但是对时间这块,由于源码中时间过滤器如下:

class DateFromToRangeFilter(RangeFilter):
    field_class = DateRangeField


class DateTimeFromToRangeFilter(RangeFilter):
    field_class = DateTimeRangeField


class IsoDateTimeFromToRangeFilter(RangeFilter):
    field_class = IsoDateTimeRangeField


class TimeRangeFilter(RangeFilter):
    field_class = TimeRangeField

当我们alt点击每个的***Field类(如DateRangeField)时,实现如下

class IsoDateTimeRangeField(RangeField):
    widget = DateRangeWidget

    def __init__(self, *args, **kwargs):
        fields = (
            IsoDateTimeField(),
            IsoDateTimeField())
        super().__init__(fields, *args, **kwargs)

可以发现widget默认为DateRangeWidget, 再看看DateRangeWidget的源码:

class DateRangeWidget(RangeWidget):
    suffixes = ['after', 'before']

所以我们在定义时间之类的range时,默认后缀为after和before,如果想要修改,修改的方式如下:

class RangeWidget(DateRangeWidget):
    suffixes = ['from', 'to']
    ......
range = django_filters.DateTimeFromToRangeFilter(field_name='pub_time', widget=RangeWidget)
# url
http://127.0.0.1:8000/spider/post?range_from=2019-06-09+00:00:00&range_to=2019-06-11+00:00:00

搜索过滤

这种方式和本质上的过滤没有区别,主要使用SearchFilter类

class PostView(mixins.ListModelMixin, GenericViewSet):
  
    queryset = Post.objects.all()
    serializer_class = PostSerializer
    pagination_class = PostPagination
    filter_backends = (DjangoFilterBackend, SearchFilter,)
    filter_class = FormFilter
    search_fields = ('=username', '@email')

同样的,使用双下划线符号对ForeignKey或ManyToManyField执行相关查找

  • '^' 以指定内容开始.

  • '=' 完全匹配

  • '@' 全文搜索(目前只支持Django的MySQL后端)

  • '$' 正则搜索

若是要排序搜索使用 OrderingFilter

    filter_backends = (filters.OrderingFilter,)
    # 指定字段搜索排序
    ordering_fields = ('username', 'email')
    # 默认字段搜索排序
    ordering = ('username',)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.