• 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

  • 相关阅读:
    二分查找算法
    http协议。会话控制cookie、session
    154. Find Minimum in Rotated Sorted Array II
    8. String to Integer (atoi)
    528. Random Pick with Weight
    415. Add Strings
    158. Read N Characters Given Read4 II
    157. Read N Characters Given Read4
    19. Remove Nth Node From End of List
    29. Divide Two Integers
  • 原文地址:https://www.cnblogs.com/cheng825/p/12099109.html
Copyright © 2020-2023  润新知