django-filter跨表過濾,區間過濾


文章目錄
django-filters

0 GitHub

1 環境

2 需求

3 起步

3.1 新建一個Django項目

3.2 settings.py

3.3 models.py

4 django REST框架簡單的過濾

4.1 沒有使用過濾

4.2 加入過濾器

5 跨表過濾

6 區間過濾

7 跨表后區間過濾

7.1 格式

django-filters

0 GitHub

https://github.com/Coxhuang/django-DjangoFilterBackend.git
1

1 環境

Django2.0.7
djangorestframework
3.8.2
django-filter==2.0.0
1
2
3

2 需求

獲取某些數據時,需要按某些字段過濾
過濾時,有些的字段是 “跨表” 的字段,該如何處理
過濾時,有些字段是 “區間” 字段(比如時間),該如何處理
過濾時,有些字段是 “跨表” 后的 “區間” 字段,又該如何處理

3 起步

3.1 新建一個Django項目

.
├── app
│ ├── init.py
│ ├── admin.py
│ ├── apps.py
│ ├── filters.py # 添加新文件
│ ├── migrations
│ ├── models.py
│ ├── tests.py
│ └── views.py
├── db.sqlite3
├── djangofilters
│ ├── init.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── manage.py
└── templates
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

3.2 settings.py

INSTALLED_APPS = [
...
'rest_framework',
'django_filters',
'app',
]
1
2
3
4
5
6

3.3 models.py

from django.db import models
class Teacher(models.Model):
"""老師表"""
name = models.CharField(verbose_name="老師姓名",max_length=16)
class Student(models.Model):
"""學生表"""
tea = models.ForeignKey(Teacher,on_delete=models.DO_NOTHING,verbose_name="老師")
name = models.CharField(verbose_name="學生姓名",max_length=16)

1
2
3
4
5
6
7
8
9

4 django REST框架簡單的過濾

4.1 沒有使用過濾

class getUserListSerializer(DynamicFieldsMixin,serializers.ModelSerializer):
teaname = serializers.CharField(label="老師姓名",source="tea.name")
class Meta:
model = models.Student
fields = ["id","name","teaname",]
class getUserListView(mixins.ListModelMixin,GenericViewSet):
queryset = models.Student.objects.all()
serializer_class = getUserListSerializer
1
2
3
4
5
6
7
8

4.2 加入過濾器

filters.py

import django_filters
from app import models
class getUserListFilter(django_filters.rest_framework.FilterSet):
class Meta:
model = models.Student
fields = ["name",]

1
2
3
4
5
6
7
views.py

...
from django_filters import rest_framework
from app.filters import getUserListFilter

class getUserListView(mixins.ListModelMixin,GenericViewSet):
...
filter_backends = (rest_framework.DjangoFilterBackend,)
filter_class = getUserListFilter
1
2
3
4
5
6
7
8

5 跨表過濾

需求:根據老師的名字過濾

class getUserListFilter(django_filters.rest_framework.FilterSet):
teaname = django_filters.CharFilter(field_name='tea__name', label="老師姓名") # 跨表操作
class Meta:
model = models.Student
fields = ["name","teaname",]
1
2
3
4
5

6 區間過濾

新增字段createDate(用戶創建時間)
createDate = models.DateTimeField(verbose_name="用戶創建時間",auto_now_add=True)
1
filters.py

class getUserListFilter(django_filters.rest_framework.FilterSet):
teaname = django_filters.CharFilter(field_name='tea__name', label="老師姓名")
RegDate = django_filters.DateFromToRangeFilter(field_name='createDate', lookup_expr='gte', label='注冊時間') # 區間過濾
class Meta:
model = models.Student
fields = ["name","teaname","RegDate",]
1
2
3
4
5
6

注意 : 在url的參數中,原來我們在filters.py中定義的變量是 “RegDate”,到了url中變成了 “RegDate_after” 和 “RegDate_before”,這是框架給我設定好的區間變量,直接使用就行

more : 更多關鍵詞,請參考文檔

7 跨表后區間過濾

需求:學生老師的薪資范圍過濾

新增字段salary(老師薪資)
filters.py

class getUserListFilter(django_filters.rest_framework.FilterSet):
teaname = django_filters.CharFilter(field_name='tea__name', label="老師姓名")
RegDate = django_filters.DateFromToRangeFilter(field_name='createDate', lookup_expr='gte', label='注冊時間')
salary = django_filters.RangeFilter(method='salary_filter', label='薪資',)
class Meta:
model = models.Student
fields = ["name","teaname","RegDate","salary"]

def salary_filter(self, queryset, name, value):

    return queryset.filter(Q(tea__salary__gte = int(value.start)) &
                           Q(tea__salary__lte = int(value.stop)))

1
2
3
4
5
6
7
8
9
10
11
12

7.1 格式

聲明
salary = django_filters.RangeFilter(method='salary_filter', label='薪資',)
1
函數
def salary_filter(self, queryset, name, value):
return queryset.filter(Q(tea__salary__gte = int(value.start)) &
Q(tea__salary__lte = int(value.stop)))
1
2
3
細節
函數名必須是 method 的值
如果是區間,可以使用django_filters.RangeFilter,如果不是區間可以使用其他
重寫函數時,里面的參數不會自動補全

使用Q時,一定不能使用or / and,只能使用 | &
return 的數值,如果使用queryset.filter(xxx).filter(xxx),那么返回的結果是所有過濾的交集,如果每個自定義函數都返回自己過濾的數據(例如,models.Student.objects.filter().filter()),那么過濾的結果是所有符合條件的並集
value的正確使用,value.start對應的是url中的min(salary_min),value.stop對應url的max(salary_max)

————————————————
版權聲明:本文為CSDN博主「Coxhuang」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/Coxhuang/article/details/86548197


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM