zoukankan      html  css  js  c++  java
  • django-filters跨表过滤

    django-filters

    #0 GitHub

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

    #1 环境

    Django==2.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/DateFilter(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
    • 细节
    1. 函数名必须是 method 的值
    2. 如果是区间,可以使用django_filters.RangeFilter,如果不是区间可以使用其他
    3. 重写函数时,里面的参数不会自动补全
    1. 使用Q时,一定不能使用or / and,只能使用 | &
    2. return 的数值,如果使用queryset.filter(xxx).filter(xxx),那么返回的结果是所有过滤的交集,如果每个自定义函数都返回自己过滤的数据(例如,models.Student.objects.filter().filter()),那么过滤的结果是所有符合条件的并集
    3. value的正确使用,value.start对应的是url中的min(salary_min),value.stop对应url的max(salary_max)
      在这里插入图片描述

    在这里插入图片描述

    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    DNNClassifier 深度神经网络 分类器
    浏览器对MP4视频 帧宽度 高度的兼容性
    UnicodeEncodeError:'latin-1' codec can't encode character
    文件夹下 文件计数
    the largest value you actually can transmit between the client and server is determined by the amount of available memory and the size of the communications buffers.
    the “identity” of an object
    广告特征 用户特征
    如果一个维度全覆盖,则有效维度应该对该维度全覆盖
    a high-level neural networks AP
    使用 LDA 挖掘的用户喜好主题
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/14705828.html
Copyright © 2011-2022 走看看