drf之過濾詳解
其實也沒有多詳,只是覺得這個功能可能很好用,就稍微學細一些,繼續學習之后可能會被其他更好用的知識替代吧
文章部分來自 https://zhuanlan.zhihu.com/p/110060840
類似在視圖中操作模型的filter,不過drf提供了過濾組件,只要簡單配置,加上指定可以提供過濾的字段,就可以快速實現像在url后面用有名分組接收參數的效果
使用filter,需要先安裝模塊,可以在pycharm里安裝也可以使用pip安裝
pip install django-filter
快速配置
# setting.py
# 需要先在應用里注冊,像rest_framework
INSTALLED_APPS = [
...
'django_filters', # 需要注冊應用,
]
# 全局配置
REST_FRAMEWORK = {
...
'DEFAULT_FILTER_BACKENDS':('django_filters.rest_framework.DjangoFilterBackend',)
}
在視圖中添加filter_fields屬性,指定可以過濾的字段
class StudentListView(ListAPIView):
queryset = Student.objects.all()
serializer_class = StudentSerializer
filter_fields = ('age', 'sex')
# 127.0.0.1:8000/four/students/?sex=1
高級配置
可以寫自己的過濾器類,在視圖中導入,可以實現模糊過濾,比如包含,大於,小於等等
過濾器類和Django中表單類極其類似,寫法基本一樣,目的是指明過濾的時候使用哪些字段進行過濾,每個字段可以使用哪些運算。運算符的寫法基本參照Django的ORM中查詢的寫法,比如:大於等於,小於等於用“gte”,“lte”等等
模型層以圖書表為例
# 單獨寫一個過濾器文件,首先導入模塊
from django_filters.rest_framework import FilterSet
class BookFilter(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
}
]