1. 程式人生 > >收貨地址--實現省市區三級聯動和使用drf-extensions擴展使用緩存

收貨地址--實現省市區三級聯動和使用drf-extensions擴展使用緩存

onf area trie resp 圖集 lan 路由 iso 輸入

主要實現省市區三級聯動和在Django REST framework中使用緩存。

在用戶錄入地址時,需要進行省市區的選擇。在頁面加載時,向後端請求省份數據,當用戶選擇確定省份後,向後端請求該省份的城市數據;在用戶選擇確定城市數據後,向後端請求該城市的區縣信息。我們把這個過程稱為省市區三級聯動。

我們新建一個應用areas來實現省市區三級聯動。

1)終端:cd meiduo_mall/meiduo_mall/apps

2)創建areas子應用:python ../../manage.py startapp areas

3)在areas/models.py中,創建省市區數據表,采用自關聯方式

from
django.db import models class Area(models.Model): """ 行政區劃 null=True:(必寫項)允許省級的父級為空 blank=True:(必寫項)約束將來在admin站點 parent表單裏可以不填 on_delete:刪除守護,比如將來需要刪除某個市,如果 不做守護,會把這個市下面的區全都刪掉 """ name = models.CharField(max_length=20, verbose_name=名稱) parent = models.ForeignKey(
self, on_delete=models.SET_NULL, related_name=subs, null=True, blank=True, verbose_name=上級行政區劃) class Meta: db_table = tb_areas verbose_name = 行政區劃 verbose_name_plural = 行政區劃 def __str__(self): return self.name

說明

  • 自關聯字段的外鍵指向自身,所以ForeignKey(‘self‘)
  • 需要使用related_name指明查詢一個行政區劃的所有下級行政區劃時,使用哪種語法查詢,如本模型類中指明通過Area模型類對象.subs查詢所有下屬行政區劃,而不是使用Django默認的Area模型類對象.area_set語法。

4)settings配置文件中安裝應用:

INSTALLED_APPS = [
       areas.apps.AreasConfig,#省市區數據
]

5)生成遷移文件: 終端命令--python manage.py makemigrations

執行遷移: 終端命令--python manage.py migrate

遷移到數據庫後,我們向數據庫中添加全國省市區數據,將areas.sql導入數據庫中。我們可以將導入數據庫的過程創建一個腳本,將areas.sql添加到scripts目錄中,在scripts目錄中創建import_areas_data_to_db.sh的shell腳本文件。打開import_areas_data_to_db.sh文件,輸入:

#!/bin/bash
#mysql -h數據庫ip地址 -u數據庫用戶名 -p 數據庫密碼 < areas.sql
mysql -h10.211.55.5 -uroot -p meiduo_mall < areas.sql

說明:以上代碼如果想以python腳本運行,#!/bin/bash 改成 #!/usr/bin/env python

終端修改文件的執行權限:chmod +x import_areas_data_to_db.sh

然後輸入執行命令導入數據:./import_areas_data_to_db.sh

文件導入數據庫工作就完成嘍。。。。。。

接下來要寫後端接口程序了············

在 areas/views.py文件中新建視圖:

from rest_framework.viewsets import ReadOnlyModelViewSet
from .models import Area
from . import serializers
# Create your views here.

# GET /areas/  ==> list
# GET /areas/<pk>/  ==? retrieve
class AreasViewSet(ReadOnlyModelViewSet):
    """提供省市區三級聯動數據"""

    # 禁用分頁
    pagination_class = None

    # 指定要輸出的數據來自哪個查詢集
    # queryset = Area.objects.all()
    def get_queryset(self):
        """根據請求的行為,過濾不同的行為對應的序列化器需要的數據"""
        if self.action == list:
            return Area.objects.filter(parent=None) # 只有當parent=None 返回的是省級數據
        else:
            return Area.objects.all()

    # 指定序列化器
    # serializer_class = ‘序列化器‘
    def get_serializer_class(self):
        """根據請求的行為,指定不同的序列化器"""
        if self.action == list:
            return serializers.AreasSerializer
        else:
            return serializers.SubsAreasSerializer

新建areas/serializers.py文件新建序列化器:

from rest_framework import serializers

from .models import Area


class AreasSerializer(serializers.ModelSerializer):
    """list 行為的序列化器"""

    class Meta:
        # 指定輸出的數據的模型類
        model = Area
        # 指定輸出的字段
        fields = (id, name)


class SubsAreasSerializer(serializers.ModelSerializer):
    """retrieve行為的序列化器"""

    # 關聯
    subs = AreasSerializer(many=True, read_only=True)

    class Meta:
        # 指定輸出的數據的模型類
        model = Area
        # 指定輸出的字段  subs=area_set
        fields = (id, name, subs)

新建areas/urls.py文件定義路由:

from rest_framework.routers import DefaultRouter
from . import views


router = DefaultRouter()
router.register(rareas, views.AreasViewSet, base_name=areas)

urlpatterns = []

urlpatterns += router.urls

在主業務邏輯應用的meiduo_mall/urls.py文件中添加此路由:

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    # 省市區
    url(r^, include(areas.urls)),
]

接下來就是添加緩存:

省市區的數據是經常被用戶查詢使用的,而且數據基本不變化,所以我們可以將省市區數據進行緩存處理,減少數據庫的查詢次數。

在Django REST framework中使用緩存,可以通過drf-extensions擴展來實現。

關於擴展使用緩存的文檔,可參考鏈接http://chibisov.github.io/drf-extensions/docs/#caching

安裝

pip install drf-extensions

使用方法

1) 直接添加裝飾器

可以在使用rest_framework_extensions.cache.decorators中的cache_response裝飾器來裝飾返回數據的類視圖的對象方法,如

class CityView(views.APIView):
    @cache_response()
    def get(self, request, *args, **kwargs):
        ...

cache_response裝飾器可以接收兩個參數

@cache_response(timeout=60*60, cache=‘default‘)
  • timeout 緩存時間
  • cache 緩存使用的Django緩存後端(即CACHES配置中的鍵名稱)即選擇的是redis數據庫的幾號數據庫(一共16個數據庫)

如果在使用cache_response裝飾器時未指明timeout或者cache參數,則會使用配置文件中的默認配置,可以通過如下方法指明:

# DRF擴展
REST_FRAMEWORK_EXTENSIONS = {
    # 緩存時間
    ‘DEFAULT_CACHE_RESPONSE_TIMEOUT‘: 60 * 60,
    # 緩存存儲
    ‘DEFAULT_USE_CACHE‘: ‘default‘,
}
  • DEFAULT_CACHE_RESPONSE_TIMEOUT 緩存有效期,單位秒
  • DEFAULT_USE_CACHE 緩存的存儲方式,與配置文件中的CACHES的鍵對應。

註意,cache_response裝飾器既可以裝飾在類視圖中的get方法上,也可以裝飾在REST framework擴展類提供的list或retrieve方法上。使用cache_response裝飾器無需使用method_decorator進行轉換。

2)使用drf-extensions提供的擴展類

drf-extensions擴展對於緩存提供了三個擴展類:

  • ListCacheResponseMixin

    用於緩存返回列表數據的視圖,與ListModelMixin擴展類配合使用,實際是為list方法添加了cache_response裝飾器

  • RetrieveCacheResponseMixin

    用於緩存返回單一數據的視圖,與RetrieveModelMixin擴展類配合使用,實際是為retrieve方法添加了cache_response裝飾器

  • CacheResponseMixin

    為視圖集同時補充List和Retrieve兩種緩存,與ListModelMixin和RetrieveModelMixin一起配合使用。

三個擴展類都是在rest_framework_extensions.cache.mixins中。

為省市區視圖添加緩存

因為省市區視圖使用了視圖集,並且視圖集中有提供ListModelMixin和RetrieveModelMixin的擴展(由ReadOnlyModelViewSet提供),所以可以直接添加CacheResponseMixin擴展類。

修改返回省市區信息的視圖:

from django.shortcuts import render
from rest_framework.viewsets import ReadOnlyModelViewSet
#添加緩存
from rest_framework_extensions.cache.mixins import CacheResponseMixin

from .models import Area
from . import serializers


# GET /areas/  ==> list
# GET /areas/<pk>/  ==? retrieve
class AreasViewSet(CacheResponseMixin,ReadOnlyModelViewSet):
    """提供省市區三級聯動數據"""

    # 禁用分頁
    pagination_class = None

    # 指定要輸出的數據來自哪個查詢集
    # queryset = Area.objects.all()
    def get_queryset(self):
        """根據請求的行為,過濾不同的行為對應的序列化器需要的數據"""
        if self.action == list:
            return Area.objects.filter(parent=None) # 只有當parent=None 返回的是省級數據
        else:
            return Area.objects.all()

    # 指定序列化器
    # serializer_class = ‘序列化器‘
    def get_serializer_class(self):
        """根據請求的行為,指定不同的序列化器"""
        if self.action == list:
            return serializers.AreasSerializer
        else:
            return serializers.SubsAreasSerializer

緩存數據保存位置與有效期的設置

我們想把緩存數據保存在redis中,且設置有效期,可以通過在配置文件中定義的方式來實現。

在settings配置文件中增加:

# DRF擴展
REST_FRAMEWORK_EXTENSIONS = {
    # 緩存時間
    DEFAULT_CACHE_RESPONSE_TIMEOUT: 60 * 60,
    # 緩存存儲
    DEFAULT_USE_CACHE: default,
}

省級聯動到此就結束了 , 下一篇繼續寫用戶的地址管理

 
 
 

收貨地址--實現省市區三級聯動和使用drf-extensions擴展使用緩存