1. 程式人生 > >【Django REST framework電商專案筆記】第05章 商品列表頁功能開發(下)

【Django REST framework電商專案筆記】第05章 商品列表頁功能開發(下)

drf中的request和response

drf 對 Django 的 request 和 response 進行了封裝 瀏覽器請求的 request 會被 drf 封裝擴充套件為標準的 http request 在基本的 httpRequest 上擴充套件,增加了對 REST 框架靈活的請求解析和請求認證的支援

Request parsing對使用者發過來的資料進行解析

data 將使用者 post 過來的資料以及 files 放到 data 裡面 包括所有的解析內容、檔案和非檔案 不僅解析 post 方法過來的內容,其他的如 put patch 都會幫我們解析

drf的過濾器

通過 drf 為我們提供的過濾功能,可以簡單快速的完成過濾

GenericViewSet 繼承的 GenericAPIView 中有一個可以供我們重寫的方法用於我們的過濾

傳統的filter 跟我們在xadmin後臺中的過濾器差不多。

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

列表頁常見的三種過濾,就是列表頁的傳統欄位精確過濾,搜尋過濾,以及排序

pip install django-filter

安裝之後加入已安裝app的列表中。

	...
	django_filters,  # 過濾器配置

settings 中配置:

REST_FRAMEWORK = {
	...
    'DEFAULT_FILTER_BACKENDS'
: ('django_filters.rest_framework.DjangoFilterBackend',) }

drf過濾器實現

from django_filters.rest_framework import DjangoFilterBackend

	...
	filter_backends = (DjangoFilterBackend,)
	filter_fields = ('name', 'shop_price') # 設定需要過濾的欄位
	

我們可以自定義我們自己的filter類,進行自定義的filter類 在 goods 目錄下新建 filters.py

# coding: utf-8
__author__ = 'Evan' from django_filters import rest_framework as filters from goods.models import Goods from django.db.models import Q class GoodsFilter(filters.FilterSet): """ 商品的過濾類 """ pricemin = filters.NumberFilter(field_name='shop_price', lookup_expr='gt') pricemax = filters.NumberFilter(field_name='shop_price', lookup_expr='lt') top_category = filters.NumberFilter(method="top_category_filter") class Meta: model = Goods fields = [ 'pricemin', 'pricemax', 'is_new', 'is_hot']

返回 views 註釋掉: filter_fields,這時候我們的 filter_fields 已經失效了

from rest_framework import filters
	...
    filter_backends = (DjangoFilterBackend,
                       filters.SearchFilter,
                       filters.OrderingFilter)
    filter_class = GoodsFilter
    search_fields = ('name', 'goods_brief', 'goods_desc')
    ordering_fields = ('sold_num', 'shop_price')

    # filter_backends = (DjangoFilterBackend,)
    # filter_fields = ('name', 'shop_price')

drf的搜尋和排序

模糊查詢

    # 行為: 名稱中包含某字元,且字元不區分大小寫
    name = filters.CharFilter(name="name", lookup_expr="icontains")

    class Meta:
        model = Goods
        fields = ['price_min', 'price_max', 'name']
from rest_framework import filters

    # 設定三大常用過濾器之DjangoFilterBackend, SearchFilter
    filter_backends = (DjangoFilterBackend, filters.SearchFilter)

上面程式碼中的 filter 一定要注意不是 django 中的 filter 而是 rest_framework 中的。不然會報錯

配置了 search_fields 之後配置我們的 search_fields

    # 設定我們的search欄位
    search_fields = ('name', 'goods_brief', 'goods_desc')

以當前欄位值開頭的,等於類似於欄位精確過濾。全文搜尋。正則表示式搜尋

search_fields = ('=username', '=email')

OrderingFilter支援排序

    # 設定三大常用過濾器之DjangoFilterBackend, SearchFilter
    filter_backends = (DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter)
    # 設定排序
    ordering_fields = ('sold_num', 'add_time')

一般全文搜尋,真正的模糊查詢是使用 elasticSearch 來做的 重寫 order 引數,來實現 url 中指定引數值

不止資料的獲取,資料的提交以及後面的 login 驗證等,都可以在這個介面介面進行操作,方便後端程式碼的除錯

class GoodsAllViewSet(CacheResponseMixin,
                      mixins.ListModelMixin,
                      mixins.RetrieveModelMixin,
                      viewsets.GenericViewSet):
    """
    商品列表 ViewSet
    包括了分頁,搜尋,過濾,排序
    """

    '''
    # queryset = Goods.objects.all() 不設定排序會報下面的錯誤:
    UnorderedObjectListWarning: Pagination may yield inconsistent results 
    with an unordered object_list: <class 'goods.models.Goods'> QuerySet.
    '''
    # queryset = Goods.objects.get_queryset().order_by('id')
    throttle_classes = (AnonRateThrottle, UserRateThrottle)
    queryset = Goods.objects.all().order_by('id')
    serializer_class = GoodsSerializer
    pagination_class = GoodsPagination

    # drf的token認證機制
    # authentication_classes = (TokenAuthentication,)

    filter_backends = (DjangoFilterBackend,
                       filters.SearchFilter,
                       filters.OrderingFilter)
    filter_class = GoodsFilter
    search_fields = ('name', 'goods_brief', 'goods_desc')
    ordering_fields = ('sold_num', 'shop_price')

CacheResponseMixin 是設定了快取,後面會用在一些頁面的顯示上,比如這裡的商品列表