queryset问题

drf中的request和response

drf对于django的request和response进行了一层封装。

浏览器请求的request会被drf进行一定的封装,扩展了标准的http request

REST frameworks Request class extends the standard HttpRequest, adding support for REST frameworks flexible request parsing and request authentication

在基本的httpRequest上进行了扩展。增加了对REST框架灵活的请求解析和请求认证的支持。

Request parsing 对于用户发过来的数据进行一定的解析

  • data 将用户post过来的数据,以及files放到data里面
  • 包括所有的解析内容,文件的,非文件的。
  • 不仅解析post方法过来的内容。其他的如put patch都会帮我们进行解析

.query_params

里面放着get请求传递过来的参数?min=10

.parsers

用户传递过来的数据有很多种类型。比如file啊。post过来的json啊。字符串。

使用drf给我们提供的各种parsers

什么类型的数据都可以接收、调用parser指定对应的解析器

Authentication

认证中的.user就能获取到当前的用户。.auth返回一些额外的信息

response根据你前台传过来的参数等给你返回

比如前台要求返回json 就返回json。 要求返回浏览器可以解析的html就返回html

mark
mark

response也是支持template_render的返回html

drf的过滤器

通过drf为我们提供的过滤功能简单快速的完成过滤

GenericViewSet继承的GenericAPIView中有一个可以供我们重写的方法用于我们的过滤

class GoodsListViewSet(mixins.ListModelMixin, viewsets.GenericViewSet):
    """
    商品列表页
    """
    # queryset是一个属性
    # good_viewset.queryset就可以访问到
    # 函数就必须调用good_viewset.get_queryset()函数
    # 如果有了下面的get_queryset。那么上面的这个就不需要了。
    # queryset = Goods.objects.all()
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination
    queryset = Goods.objects.all()

    def get_queryset(self):
        # 价格大于100的
        price_min = self.request.query_params.get(price_min, 0)
        if price_min:
            self.queryset = Goods.objects.filter(shop_price__gt=price_min)
        return self.queryset

老师使用的drf中的这里将queryset 放在get 函数内部返回即可。
经我测试,新版本必须如上面代码所示

可能的报错:

    assert queryset is not None, `base_name` argument not specified, and could  AssertionError: `base_name` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.

可以说报错信息写的很明显了。我们缺少一个queryset的属性。

可能的警告:

 UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <class goods.models.Goods> QuerySet.
  paginator = self.django_paginator_class(queryset, page_size)

这个是因为我们没有为我们的返回数据添加一个指定的排序方式。

self.queryset = Goods.objects.filter(shop_price__gt=price_min).order_by(-add_time)

添加指定的排序方式消除警告。

访问: http://127.0.0.1:8000/goods/?page=2&price_min=100

可以看到过滤效果

过滤的优化

即使这样我们还是觉得这个过滤实在是太麻烦了。

又要获取参数,又要判断参数是否存在,存在之后转化为int(我没转)

虽然现在看起来代码不多,但是如果有很多的过滤参数,那么过滤这件事将会变得较为复杂。

使用drf 的 filter

http://www.django-rest-framework.org/api-guide/filtering/

mark
mark

传统的filter 跟我们在xadmin后台中的过滤器差不多。

  • searchFilter 它的行为是search行为。
  • 排序的filter

列表页常见的三种过滤,就是列表页的传统字段精确过滤,搜索过滤,以及排序。

DjangoFilterBackend

pip install django-filter
  • 安装之后加入已安装app的列表中。
django_filters,
  • 添加设置。既然是默认设置一般都自动设置好了。
REST_FRAMEWORK = {
    DEFAULT_FILTER_BACKENDS: (django_filters.rest_framework.DjangoFilterBackend,)
}
  • 开始使用,首先import进来

goods/views.py

from django_filters.rest_framework import DjangoFilterBackend

官方示例:

class UserListView(generics.ListAPIView):
    ...
    filter_backends = (DjangoFilterBackend,)

我们需要在我们的view中设置

mark
mark
filter_backends = (DjangoFilterBackend,)

我们既然决定使用djangofilter那么就可以不用get_queryset方法了。注释掉

  • 设置我们需要过滤的字段

官方示例:

class ProductList(generics.ListAPIView):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_fields = (category, in_stock)

我们的实践:

    # 设置我们需要进行过滤的字段
    filter_fields = (name, shop_price)
mark
mark

可以看到我们页面的右上多了一个过滤器。这是一个精确地等于的过滤器

?name=&shop_price=100

我们想模糊搜索。或者搜索一个区间。

https://django-filter.readthedocs.io/en/master/

他不但是一个满足drf的filter 也是用于

filter_class

我们可以自定义我们自己的filter类,进行自定义的filter类

在goods目录下新建filters.py

# -*- coding:utf-8 _*-
__author__ = mtianyan
__date__ = 2018/03/03 00:44

from django_filters import rest_framework as filters
from goods.models import Goods


class GoodsFilter(filters.FilterSet):
    """
    商品的过滤类
    """
    # 指定字段以及字段上的行为,在shop_price上大于等于
    price_min = filters.NumberFilter(name="shop_price", lookup_expr=gte)
    price_max = filters.NumberFilter(name="shop_price", lookup_expr=lte)

    class Meta:
        model = Goods
        fields = [price_min, price_max]
    # 设置三大常用过滤器之DjangoFilterBackend
    filter_backends = (DjangoFilterBackend,)

    # 设置filter的类为我们自定义的类
    filter_class = GoodsFilter

注释掉: filter_fields,这时候我们的filter_fields已经失效了

mark
mark

过滤器没有确定的按钮是因为继承错了。应该继承rf的import rest_framework as filters

drf的搜索和排序

我们不一定在这个类里面使用它自带的过滤方法。还可以自定义我们的过滤方法,这个在后面会讲到。

https://code.ziqiangxuetang.com/django/django-queryset-api.html

Django QuerySetAPI

模糊查询

    # 行为: 名称中包含某字符,且字符不区分大小写
    name = filters.CharFilter(name="name", lookup_expr="icontains")

    class Meta:
        model = Goods
        fields = [price_min, price_max, name]

配置drf里面的SearchFilter

http://www.django-rest-framework.org/api-guide/filtering/#searchfilter

from rest_framework import filters

    # 设置三大常用过滤器之DjangoFilterBackend, SearchFilter
    filter_backends = (DjangoFilterBackend, filters.SearchFilter)

上面代码中的filter一定要注意不是django中的filter而是restframe中的。不然会报错。

    filter_backends = (DjangoFilterBackend, filters.SearchFilter)
AttributeError: module django_filters.rest_framework.filters has no attribute SearchFilter

配置了search_fields之后配置我们的search_fields

    # 设置我们的search字段
    search_fields = (name, goods_brief, goods_desc)

search_fields.

  • ^ Starts-with search.
  • = Exact matches.
  • @ Full-text search. (Currently only supported Djangos MySQL backend.)
  • $ Regex search.

以当前字段值开头的,等于类似于字段精确过滤。全文搜索。正则表达式搜索

search_fields = (=username, =email)

By default, the search parameter is named search, but this may be overridden with the SEARCH_PARAM setting.

默认的search参数为

mark
mark

search。可以在设置中覆盖SEARCH_PARAM 进行自定义。

可以为多个字段配置不同精度的搜索。比如name是精确搜索,简介是模糊搜索这种。

OrderingFilter支持排序

    # 设置三大常用过滤器之DjangoFilterBackend, SearchFilter
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    # 设置排序
    ordering_fields = (sold_num, add_time)

一般全文搜索,真正的模糊查询是使用elasticSearch来做的。

but this may by overridden with the ORDERING_PARAM setting.

重写order 参数。来实现url中指定参数值

不止数据的获取,数据的提交以及后面的login验证等,都可以在这个界面进行操作。

总结

  1. view_base中通过django自身的原生view实现了商品列表页。
  2. 自己序列化 - model_to_dict方法 - 使用Serializer - JSonresponse
  3. api view generics - viewsets
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值