您现在的位置是: 网站首页 >Django >Vue+Django REST framework前后端分离生鲜电商 Django

【Vue+DRF生鲜电商】09.使用DRF的filter过滤商品列表

admin2019年4月24日 17:48 Django | Python | Vue 2950人已围观

Vue+Django REST framework前后端分离生鲜电商简介 Vue+Django REST framework 打造前后端分离的生鲜电商项目(慕课网视频)。 Github地址:https://github.com/xyliurui/DjangoOnlineFreshSupermarket ; Django版本:2.2、djangorestframework:3.9.2。 前端Vue模板可以直接联系我拿。

### DRF过滤商品列表 `GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet)`继承的`viewsets.GenericViewSet`(`GenericViewSet(ViewSetMixin, generics.GenericAPIView)`)继承的`GenericAPIView(views.APIView)`提供了一个`get_queryset()`方法,可以通过这个方法,进行过滤 ```python # 源码内容 def get_queryset(self): queryset = self.queryset if isinstance(queryset, QuerySet): # Ensure queryset is re-evaluated on each request. queryset = queryset.all() return queryset ``` #### 使用get_queryset查询函数 修改 views.py 中的视图 ```python class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination def get_queryset(self): return Goods.objects.filter(shop_price__gt=120) ``` 筛选商店价格大于120元的数据,刷新 http://127.0.0.1:8000/goods/ ![BLOG_20190424_175203_98](/media/blog/images/2019/04/BLOG_20190424_175203_98.png "博客图集BLOG_20190424_175203_98.png") 可以看到总的数量已经发生变化。 #### 获取url的参数request.query_params,传递价格区间 参考 https://www.django-rest-framework.org/api-guide/requests/#query_params `request.query_params`是`request.GET`的更正确的同义词。 为了使代码更清晰,建议使用**`request.query_params`**而不是Django的标准request.GET。这样做将有助于保持代码库更加正确和明显——任何HTTP方法类型都可能包含查询参数,而不仅仅是GET请求。 修改 views.py 增加过滤参数 ```python class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination def get_queryset(self): queryset = self.queryset # 传递价格区间的参数 price_min = self.request.query_params.get('price_min') if price_min: queryset = queryset.filter(shop_price__gte=price_min) return queryset ``` 现在访问 http://127.0.0.1:8000/goods/?price_min=160 指定过滤条件,最小价格为160 ![BLOG_20190424_175142_69](/media/blog/images/2019/04/BLOG_20190424_175142_69.png "博客图集BLOG_20190424_175142_69.png") 但是如果过滤条件很多的情况,就需要加入很多的筛选,也就是`get_queryset`函数需要获取每个参数及其值,然后在查询集进行过滤,比较麻烦 #### 使用DjangoFilterBackend 参考 https://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend `django-filter`库包含一个`DjangoFilterBackend`类,它支持REST框架的高度可定制字段过滤。 要使用`DjangoFilterBackend`,首先安装`pip install django-filter`。然后将`django_filters`添加到Django的`INSTALLED_APPS` ```python INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 添加drf应用 'rest_framework', 'django_filters', # 注册富文本编辑器ckeditor 'ckeditor', # 注册富文本上传图片ckeditor_uploader 'ckeditor_uploader', 'users.apps.UsersConfig', 'goods.apps.GoodsConfig', 'trade.apps.TradeConfig', 'user_operation.apps.UserOperationConfig' ] ``` 修改 views.py 增加商品列表的过滤器 ```python from django_filters.rest_framework import DjangoFilterBackend class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend,) # 将过滤器后端添加到单个视图或视图集 filterset_fields = ('name', 'goods_desc', ) ``` 当搜索一个name完整名称显示如下,这时url为 http://127.0.0.1:8000/goods/?name=%E6%96%B0%E9%B2%9C%E6%B0%B4%E6%9E%9C%E7%94%9C%E8%9C%9C%E9%A6%99%E8%84%86%E5%8D%95%E6%9E%9C%E7%BA%A6800%E5%85%8B&goods_desc= : ![BLOG_20190424_175130_18](/media/blog/images/2019/04/BLOG_20190424_175130_18.png "博客图集BLOG_20190424_175130_18.png") 但是,如果要模糊搜索,这时候url为 http://127.0.0.1:8000/goods/?name=%E6%B0%B4%E6%9E%9C&goods_desc= ![BLOG_20190424_175114_71](/media/blog/images/2019/04/BLOG_20190424_175114_71.png "博客图集BLOG_20190424_175114_71.png") 这一看到,是过滤不出结果的,因为这是一个 **等式** 的匹配 可以查看官方文档 https://django-filter.readthedocs.io/en/master/guide/rest_framework.html 如何自定义filter,可以参考 https://django-filter.readthedocs.io/en/master/guide/rest_framework.html#adding-a-filterset-with-filterset-class 首先,在应用下创建 filters.py 文件,用于放置所有的filter ![BLOG_20190424_175058_56](/media/blog/images/2019/04/BLOG_20190424_175058_56.png "博客图集BLOG_20190424_175058_56.png") 修改添加以下内容 ```python # filters.py from django_filters import rest_framework as filters from .models import Goods class GoodsFilter(filters.FilterSet): """ 商品的过滤类 """ name = filters.CharFilter(field_name='name', lookup_expr='contains') # 包含关系,模糊匹配 goods_desc = filters.CharFilter(field_name='name', lookup_expr='contains') min_price = filters.NumberFilter(field_name="shop_price", lookup_expr='gte') # 自定义字段 max_price = filters.NumberFilter(field_name="shop_price", lookup_expr='lte') class Meta: model = Goods fields = ['name', 'goods_desc', 'min_price', 'max_price'] ``` 例如上方的`field_name='name', lookup_expr='contains'`就类似于Django中`queryset.filter(name__contains=xxx)`,`field_name`需和模型中的字段保持一致,而前面的字段就是url中的参数。`Meta`需要指定操作的模型名以及对应的字段。 修改 views.py ,添加自定义过滤类`filterset_class = GoodsFilter` ```python from django_filters.rest_framework import DjangoFilterBackend from .filters import GoodsFilter class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend,) # 将过滤器后端添加到单个视图或视图集 filterset_class = GoodsFilter ``` ![BLOG_20190424_175036_17](/media/blog/images/2019/04/BLOG_20190424_175036_17.png "博客图集BLOG_20190424_175036_17.png") 输入字段进行过滤,这时候url为: http://127.0.0.1:8000/goods/?name=%E6%B0%B4%E6%9E%9C&goods_desc=&min_price=150&max_price=180 #### 使用SearchFilter 参考: https://www.django-rest-framework.org/api-guide/filtering/#searchfilter 搜索最适合模糊匹配 `SearchFilter`类支持简单的基于查询参数的搜索,并且基于Django管理员的搜索功能。 `search_fields`属性应该是模型中文本类型字段的名称列表,例如CharField或TextField。 修改 views.py ```python from rest_framework import viewsets, filters from django_filters.rest_framework import DjangoFilterBackend class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter,) # 将过滤器后端添加到单个视图或视图集 filterset_class = GoodsFilter search_fields = ('name', 'goods_desc') # 搜索字段 ``` 刷新页面,输入搜索字段(模糊匹配) ![BLOG_20190424_175026_53](/media/blog/images/2019/04/BLOG_20190424_175026_53.png "博客图集BLOG_20190424_175026_53.png") 这时候url为: http://127.0.0.1:8000/goods/?search=%E6%B0%B4%E6%9E%9C 可以搜索对应的内容。 也可以对一个外键或`ManyToManyField`执行相关的查找,使用查找API双下划线表示法: ```python search_fields = ('name', 'goods_desc', 'category__name') # 最后表示搜索外键分类名称 ``` 默认情况下,搜索将使用不区分大小写的部分匹配。搜索参数可以包含多个搜索项,这些搜索项应该用空格和/或逗号分隔。如果使用多个搜索项,则仅当所提供的所有项都匹配时,才会在列表中返回对象。 搜索行为可能受到search_fields前置各种字符的限制。 - `^`:以搜索的文本开始。 - `=`:精确匹配。 - `@`:全文搜索。(目前只支持Django的MySQL后端)。 - `$`:正则表达式搜索。 #### 使用OrderingFilter 参考: https://www.django-rest-framework.org/api-guide/filtering/#orderingfilter `OrderingFilter`类支持简单的查询参数控制的结果排序。 默认情况下,查询参数名为`ordered`,但是可以通过`ORDERING_PARAM`设置覆盖该参数。 修改 views.py ```python class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet): """ 显示商品列表,分页、过滤、搜索、排序 """ queryset = Goods.objects.all() # 使用get_queryset函数,依赖queryset的值 serializer_class = GoodsSerializer pagination_class = GoodsPagination filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter,) # 将过滤器后端添加到单个视图或视图集 filterset_class = GoodsFilter search_fields = ('name', 'goods_desc', 'category__name') # 搜索字段 ordering_fields = ('click_num', 'sold_num', 'shop_price') # 排序 ``` 访问页面点击任意排序 ![BLOG_20190424_174958_52](/media/blog/images/2019/04/BLOG_20190424_174958_52.png "博客图集BLOG_20190424_174958_52.png") 这时候url为: http://127.0.0.1:8000/goods/?ordering=shop_price 如果是倒排序,则url为: http://127.0.0.1:8000/goods/?ordering=-shop_price 当然,也可以根据过滤后的内容进行排序 ![BLOG_20190424_174945_29](/media/blog/images/2019/04/BLOG_20190424_174945_29.png "博客图集BLOG_20190424_174945_29.png") 这时候url为: http://127.0.0.1:8000/goods/?goods_desc=&max_price=&min_price=&name=%E6%B0%B4%E6%9E%9C&ordering=-shop_price

很赞哦! (1)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行2077天
  • 系统信息:Linux
  • 后台程序:Python: 3.8.10
  • 网站框架:Django: 3.2.6
  • 文章统计:256 篇
  • 文章评论:60 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 公众号:微信扫描二维码,关注我们
  • QQ群:QQ加群,下载网站的学习源码
返回
顶部
标题 换行 登录
网站