zoukankan      html  css  js  c++  java
  • python测试开发django169.过滤器djangofilter 入门使用 上海

    前言

    在管理后台查询的时候,经常有需要查询包含某个内容,按时间段查询,或者商品价格大于多少,小于多少各种查询条件。
    django-filter 过滤器专门解决这种查询的问题。

    环境准备

    使用pip安装django-filter,目前安装的版本v2.2.0

    pip install django-filter
    

    在setting.py添加django_filtersINSTALLED_APPS

    INSTALLED_APPS = [
        ...
        'django_filters',
    ]
    

    Django-filter 已针对所有支持的 Python 和Django版本以及最新版本的 Django REST Framework ( DRF ) 进行了测试。
    python:3.5、3.6、3.7、3.8
    django:2.2、3.0、3.1
    DRF : 3.10+

    简单入门

    Django-filter 提供了一种基于用户提供的参数过滤查询集的简单方法。
    假设我们有一个Product模型,我们想让我们的用户过滤他们在列表页面上看到的产品。

    先设计模型

    class Manufacturer(models.Model):
        name = models.CharField(max_length=255)
        city = models.CharField(max_length=255)
    
    
    class Product(models.Model):
        name = models.CharField(max_length=255)
        price = models.DecimalField(max_digits=10, decimal_places=2)
        description = models.TextField()
        release_date = models.DateField()
        manufacturer = models.ForeignKey(Manufacturer,
                                         on_delete=models.CASCADE)
    
    

    过滤器设置,希望让我们的用户根据名称、价格或发布日期进行过滤

    • exact 精准查找,等价于filter(name=xx),对应sql语句 where name='xx';
    • iexact 使用 like 进行查找, 对应sql语句where name like 'xx';

    过滤器类似于 Django 的 ModelForm。参考之前的https://www.cnblogs.com/yoyoketang/p/15013472.html

    import django_filters
    
    class ProductFilter(django_filters.FilterSet):
        name = django_filters.CharFilter(lookup_expr='iexact')
    
        class Meta:
            model = Product
            fields = ['price', 'release_date']
    

    以上为"价格"和"发布日期"字段生成"精确"查找。

    写个视图

    def product_list(request):
        f = ProductFilter(request.GET, queryset=Product.objects.all())
        return render(request, 'demo.html', {'filter': f})
    

    template模板

    <body>
    
        <form method="get">
            {{ filter.form.as_p }}
            <input type="submit" />
        </form>
        {% for obj in filter.qs %}
            {{ obj.name }} - ${{ obj.price }}<br />
        {% endfor %}
    
    </body>
    

    urls.py配置个访问地址

    url(r'^product$', views.product_list)
    

    浏览器访问

    不输入查询内容,默认查询全部,可以根据name/price/release_date查询

    该form属性包含一个普通的 Django 表单,当我们遍历 时,FilterSet.qs我们会得到结果查询集中的对象。

    FilterSet.qs查询结果

    FilterSet.qs 查询的结果是 QuerySet 集合,可以转成 json 格式

    from django.forms.models import model_to_dict
    
    
    def product_list(request):
        f = ProductFilter(request.GET, queryset=Product.objects.all())
        s = [model_to_dict(i) for i in f.qs]
        return JsonResponse({"code": 0, "msg": "success", "data": s})
    

    查询结果

    {
    	"code": 0,
    	"msg": "success",
    	"data": [{
    		"id": 1,
    		"name": "\u60a0\u60a0",
    		"price": "22.23",
    		"description": "aa",
    		"release_date": "2021-11-08",
    		"manufacturer": 1
    	}, {
    		"id": 2,
    		"name": "yy",
    		"price": "101.00",
    		"description": "aa",
    		"release_date": "2021-11-08",
    		"manufacturer": 1
    	}]
    }
    

    .qs过滤

    要按request对象过滤主查询集,只需覆盖该 FilterSet.qs属性。例如,您可以将博客文章过滤为仅发布的文章和登录用户拥有的文章)。

    class ArticleFilter(django_filters.FilterSet):
    
        class Meta:
            model = Article
            fields = [...]
    
        @property
        def qs(self):
            parent = super().qs
            author = getattr(self.request, 'user', None)
    
            return parent.filter(is_published=True) \
                | parent.filter(author=author)
    

    过滤相关查询集 ModelChoiceFilter

    ModelChoiceFilter和ModelMultipleChoiceFilter 支持可调用的行为。
    如果传递了一个可调用对象,它将以 request 为唯一参数进行调用 。这允许您执行相同类型的基于请求的过滤,而无需求助于覆盖 FilterSet.init.

    def departments(request):
        if request is None:
            return Department.objects.none()
    
        company = request.user.company
        return company.department_set.all()
    
    class EmployeeFilter(filters.FilterSet):
        department = filters.ModelChoiceFilter(queryset=departments)
        ...
    

    自定义过滤字段 Filter.method

    您可以通过指定 method 执行过滤来控制过滤器的行为。在方法参考中查看更多信息。请注意,您可以访问过滤器集的属性,例如 request.

    class F(django_filters.FilterSet):
        username = CharFilter(method='my_custom_filter')
    
        class Meta:
            model = User
            fields = ['username']
    
        def my_custom_filter(self, queryset, name, value):
            return queryset.filter(**{
                name: value,
            })
    

    声明过滤器

    声明式语法在创建过滤器时为您提供了最大的灵活性,但它相当冗长。我们将使用下面的例子来勾勒核心过滤器参数上 FilterSet:

    class ProductFilter(django_filters.FilterSet):
        price = django_filters.NumberFilter()
        price__gt = django_filters.NumberFilter(field_name='price', lookup_expr='gt')
        price__lt = django_filters.NumberFilter(field_name='price', lookup_expr='lt')
    
        release_year = django_filters.NumberFilter(field_name='release_date', lookup_expr='year')
        release_year__gt = django_filters.NumberFilter(field_name='release_date', lookup_expr='year__gt')
        release_year__lt = django_filters.NumberFilter(field_name='release_date', lookup_expr='year__lt')
    
        manufacturer__name = django_filters.CharFilter(lookup_expr='icontains')
    
        class Meta:
            model = Product
    

    过滤器有两个主要参数:

    • field_name:要过滤的模型字段的名称。您可以使用 Django 的__语法遍历“关系路径”来过滤相关模型上的字段。例如:manufacturer__name。
    • lookup_expr:过滤时使用的字段查找。__ 可以再次使用Django 的语法来支持查找转换。例如:year__gte。

    字段field_name和字段一起lookup_expr代表一个完整的 Django 查找表达式。Django 的查找参考中提供了查找表达式的详细说明。django-filter 支持包含转换和最终查找的表达式。

    使用 Meta.fields 生成过滤器

    FilterSet Meta 类提供了一个fields属性,可用于轻松指定多个过滤器,而无需大量代码重复。基本语法支持多个字段名称的列表:

    import django_filters
    
    class ProductFilter(django_filters.FilterSet):
        class Meta:
            model = Product
            fields = ['price', 'release_date']
    

    以上为“价格”和“发布日期”字段生成“精确”查找。此外,字典可用于为每个字段指定多个查找表达式:

    import django_filters
    
    class ProductFilter(django_filters.FilterSet):
        class Meta:
            model = Product
            fields = {
                'price': ['lt', 'gt'],
                'release_date': ['exact', 'year__gt'],
            }
    

    以上将生成 'price__lt'、'price__gt'、'release_date' 和 'release_date__year__gt' 过滤器。

    过滤器查找类型“精确”是隐式默认值,因此永远不会添加到过滤器名称中。在上面的示例中,发布日期的确切过滤器是“release_date”,而不是“release_date__exact”。这可以被 FILTERS_DEFAULT_LOOKUP_EXPR 设置覆盖。
    

    类中fields序列中的项目Meta可能包括“关系路径”,使用 Django 的__语法过滤相关模型上的字段:

    class ProductFilter(django_filters.FilterSet):
        class Meta:
            model = Product
            fields = ['manufacturer__country']
    

    覆盖默认过滤器

    像django.contrib.admin.ModelAdmin,它可以覆盖默认的过滤器使用相同类型的所有车型领域 filter_overrides的Meta类:

    class ProductFilter(django_filters.FilterSet):
    
        class Meta:
            model = Product
            fields = {
                'name': ['exact'],
                'release_date': ['isnull'],
            }
            filter_overrides = {
                models.CharField: {
                    'filter_class': django_filters.CharFilter,
                    'extra': lambda f: {
                        'lookup_expr': 'icontains',
                    },
                },
                models.BooleanField: {
                    'filter_class': django_filters.BooleanFilter,
                    'extra': lambda f: {
                        'widget': forms.CheckboxInput,
                    },
                },
            }
    

    更多使用参考官方文档https://django-filter.readthedocs.io/en/stable/guide/install.html

  • 相关阅读:
    PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
    TP5安装workerman版本的坑
    下载git2.2.1并将git添加到环境变量中
    RedHat安装git报错 expected specifier-qualifier-list before ‘z_stream’
    Git出现fatal: Unable to find remote helper for 'https'
    ThinkPHP5实现定时任务
    php一行代码获取本周一,本周日,上周一,上周日,本月一日,本月最后一日,上月一日,上月最后一日日期
    git 查看日志记录
    程序员必读之软件架构 读书笔记
    centos7 安装桌面
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/15526866.html
Copyright © 2011-2022 走看看