django model filter_Django-filter,让过滤如此简单

在DRF框架的使用中,一个比较让人头疼的问题是,怎么满足前端那变态的数据过滤需求,特别当前端提供所谓的灵活查询,过滤条件更是五花八门,比如一般前端查询都简单判等查询:

path('book/<int:id>',views.BooksView.as_view(),name='book')
它对应的请求:
http://127.0.0.1:9000/book/1/

怎么查询书名中包含“英”字,日期大于“2019-3-14”等等诸如此类的请求。Django-filter这个组件就是要解决这样的问题。

1. 安装配置

Django-filter支持的Python版本和Django版本、DRF版本如下:

  • Python: 3.5, 3.6, 3.7, 3.8
  • Django: 1.11, 2.0, 2.1, 2.2, 3.0
  • DRF: 3.10+

在虚拟开发环境中安装:

pip install django-filter

在Django的项目配置文件中安装并配置django_filters应用:

INSTALLED_APPS = [
    ...
    'django_filters',
]

REST_FRAMEWORK = {
   # 过滤器默认后端
    'DEFAULT_FILTER_BACKENDS': (
           'django_filters.rest_framework.DjangoFilterBackend',),
}

2.使用流程

我们通过一个简单的图书查询来说明如果在DRF中使用Django-filter过滤器。图书模型如下:

# models.py
class Bookinfo(models.Model):
    btitle = models.CharField(max_length=200,verbose_name='标题')
    bpub_date = models.DateField(blank=True, null=True,verbose_name='出版日期')
    bread = models.IntegerField(null=True,verbose_name='阅读数量')
    bcomment = models.IntegerField(null=True,verbose_name='评论数量')
    bimage = models.CharField(max_length=200, blank=True, null=True,verbose_name='图片')

    class Meta:
        db_table = 'bookinfo'
        verbose_name = "图书"

序列化类:

#serializers.py
class BookInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bookinfo
        fields = "__all__"

我们需要自定义过滤器类:

#filters.py
from django_filters import rest_framework as filters

from App.models import Bookinfo


class BookFilter(filters.FilterSet):
    class Meta:
        min_read = filters.NumberFilter(field_name="bread", lookup_expr='gte')
        max_read = filters.NumberFilter(field_name="bread", lookup_expr='lte')
        model = Bookinfo  # 模型名
        fields = {
            'btitle':['icontains'],  
            'bcomment':['gte','lte'],
        }

在视图中

# views.py

在浏览器中测试

v2-c525b0666c1d919fdce7d5c25def621f_b.jpg
图1 过滤器的使用

3.详解过滤器类

过滤器类和Django中表单类极其类似,写法基本一样,目的是指明过滤的时候使用哪些字段进行过滤,每个字段可以使用哪些运算。运算符的写法基本参照Django的ORM中查询的写法,比如:大于等于,小于等于用"gte",“lte”等等

可以通过模型快速构建过滤器类

class BookFilter(filters.FilterSet):
    class Meta:
        model = Bookinfo   # 模型名
        fields = ['btitle','bcomment']  # 可以使用的过滤字段

Meta中出现的fields是指过滤条件中可以出现的字段,默认是精确判等,查询的时候可以这样用:

# bcomment=80
http://127.0.0.1:8000/book/?btitle=&bcomment=80

如果不是判等,可以自定义过滤字段进行过滤:

  • 过滤器中常用的字段类型,这些类型要输模型中对应字段类型兼容
CharFilter         字符串类型
BooleanFilter      布尔类型
DateTimeFilter     日期时间类型
DateFilter         日期类型
DateRangeFilter    日期范围
TimeFilter         时间类型
NumberFilter       数值类型,对应模型中IntegerField, FloatField, DecimalField
  • 参数说明:
field_name: 过滤字段名,一般应该对应模型中字段名
lookup_expr: 查询时所要进行的操作,和ORM中运算符一致
  • Meta字段说明
model: 引用的模型,不是字符串
fields:指明过滤字段,可以是列表,列表中字典可以过滤,默认是判等;也可以字典,字典可以自定义操作
exclude = ['password'] 排除字段,不允许使用列表中字典进行过滤

自定义过滤字段:

class BookFilter(filters.FilterSet):
    btitle = filters.CharFilter(field_name='title',lookup_expr='icontains')
    pub_year = filters.CharFilter(field_name='bpub_date',lookup_expr='year')
    pub_year__gt = filters.CharFilter(field_name='bpub_date',lookup_expr='year__gt')
    bread__gt = filters.NumberFilter(field_name='bread',lookup_expr="gt")
    bread__lt = filters.NumberFilter(field_name='bread',lookup_expr="lt")

    class Meta:
        model = Bookinfo
        fields = ['title','bread','bcomment']

自定义字段名可以和模型中不一致,但一定要用参数field_name指明对应模型中的字段名

日期查询

#定义按年查询,
pub_year = filters.CharFilter(field_name='bpub_date',lookup_expr='year')
# 年份应该大于某值
pub_year__gt = filters.CharFilter(field_name='bpub_date',lookup_expr='year__gt')
#年份应该小于某值
bread__lt = filters.NumberFilter(field_name='bread',lookup_expr="lt")
示例:
http://127.0.0.1:8000/book/?title=&bread=&bcomment=&btitle=&pub_year=&pub_year__gt=2014&bread__gt=&bread__lt=
查询结果:
[
    {
        "id": 1,
        "title": "射雕英雄传",
        "bpub_date": "2020-02-18",
        "bread": 30,
        "bcomment": 80,
        "bimage": null
    }
]

标题查询

# btitle查询的时候可以进行包含查询,icontains在ORM中表示不区分大小的包含
btitle = filters.CharFilter(field_name='btitle',lookup_expr='icontains')
示例:
http://127.0.0.1:8000/book/?title=&bread=&bcomment=&btitle=%E5%B0%84%E9%9B%95&pub_year=&pub_year__gt=&bread__gt=&bread__lt=
结果:
[
    {
        "id": 1,
        "title": "射雕英雄传",
        "bpub_date": "2020-02-18",
        "bread": 30,
        "bcomment": 80,
        "bimage": null
    }
]

阅读数查询

# 阅读数大于
bread__gt = filters.NumberFilter(field_name='bread',lookup_expr="gt")
# 阅读数小于
bread__lt = filters.NumberFilter(field_name='bread',lookup_expr="lt")

示例:
http://127.0.0.1:8000/book/?title=&bread=&bcomment=&btitle=&pub_year=&pub_year__gt=&bread__gt=20&bread__lt=100
结果:
[
    {
        "id": 1,
        "title": "射雕英雄传",
        "bpub_date": "2020-02-18",
        "bread": 30,
        "bcomment": 80,
        "bimage": null
    },
    {
        "id": 6,
        "title": "连城诀",
        "bpub_date": "2009-10-23",
        "bread": 30,
        "bcomment": 90,
        "bimage": null
    }
]

限于篇幅,字段列表的字典形式将在后续篇章中讲述,敬请关注。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值