收货地址--实现省市区三级联动和使用drf-extensions扩展使用缓存

主要实现省市区三级联动和在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(r‘areas‘, 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‘,
}

省级联动到此就结束了 , 下一篇继续写用户的地址管理

 
 
 

原文地址:https://www.cnblogs.com/cl-python/p/9251261.html

时间: 2024-10-13 16:33:39

收货地址--实现省市区三级联动和使用drf-extensions扩展使用缓存的相关文章

ios收货地址三级联动选择

这次的需求,是省市区三级联动选择,并且市的选择要根据省的id,然后区的选择要根据市的id 每次都要进行网络请求,关键代码,其实是 //监听轮子的移动 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component; 然后我就上传我的代码,这个代码我也是根据别人的修改的,因为需求不一样 1,创建一个View // //  IWAreaPickerVi

WheelView实现省市区三级联动(数据库实现版本号附带完整SQL及数据)

近期在实现收货地址功能,用到了省市区三级联动效果,网上找到一般都是xml或json.数据源陈旧改动麻烦.改动了一下使用数据库方式实现了一下 数据源解决.因为数据量比較大通过初始化批量运行SQL的方式不合适,费时不说还easy出错,我採用的是在电脑上创建好数据库然后把数据库文件放到程序里边,通过以下这种方法能够把db文件复制到随意文件夹下.demo中我把文件放在了raw文件夹下 /** * * @param inStream * @param fileNme 文件名称 * @param newPa

Android省市区三级联动滚轮选择(真实项目中提取出来的组件)

最近项目要做一个,类似淘宝手机客户端的,选择收货地址的三级联动滚动选择组件,下面是它的大致界面截图: 在IOS中有个叫UIPickerView的选择器,并且在dataSource中定义了UIPickerView的数据源和定制内容,所以用只要熟悉它的基本用法,要实现这么个三级联动滑动选择是挺简单的. 言归正传,今天讨论的是在Android里面如何来实现这么个效果,那么如何实现呢??? 相信部分童鞋首先想到的是android.widget.DatePicker和android.widget.Time

微信支付开发(7) 收货地址共享接口V2

在这篇微信公众平台开发教程中,我们将介绍如何在网页中实现获取收货地址的功能. 收货地址共享接口 在2016年4月13日 进行过升级,2016年5月20日之后只能使用新接口,本教程为新版接口的教程! 本文分为以下二个部分: 生成JS-SDK权限验证签名 实现获取共享收货地址 一.微信JS-SDK 1. 获得Access Token access token的获得方法在前面有介绍,详情见 微信公众平台开发(26) ACCESS TOKEN 2. 获取jsapi_ticket 生成签名之前必须先了解一

微信支付v3开发(6) 收货地址共享接口

请看新版教程  微信支付开发(7) 收货地址共享接口V2 本文介绍微信支付下的收货地址共享接口的开发过程. 一. 简单介绍 微信收货地址共享,是指用户在微信浏览器内打开网页,填写过地址后,兴许能够免填写支持高速选择.也可添加和编辑. 此地址为用户属性.可在各商户的网页中共享使用.支持原生控件填写地址.地址数据会传递到商户. 地址共享是基于微信JavaScript API 实现.仅仅能在微信内置浏览器中使用,其它浏览器调用无效. 同一时候,须要微信5.0 版本号才干支持,建议通过user agen

Android之省市区三级联动

最近项目要做一个电商APP,选择收货地址的三级联动滚动选择组件, 控件用起来非常简单 ,下面是它的运行效果: 布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:su="http://schemas.android.com/apk/res-auto

微信支付开发(6) 收货地址共享接口

关键字:微信支付 收货地址共享作者:方倍工作室原文: http://www.cnblogs.com/txw1958/p/weixin-editAddress.html 本文介绍微信支付下的收货地址共享接口的开发过程. 一. 简介 微信收货地址共享,是指用户在微信浏览器内打开网页,填写过地址后,后续可以免填写支持快速选择,也可增加和编辑.此地址为用户属性,可在各商户的网页中共享使用.支持原生控件填写地址,地址数据会传递到商户. 地址共享是基于微信JavaScript API 实现,只能在微信内置浏

微信支付开发(6) 收货地址共享接口 【转发收藏】

作者:方倍工作室原文: http://www.cnblogs.com/txw1958/p/weixin-editAddress.html 本文介绍微信支付下的收货地址共享接口的开发过程. 一. 简介 微信收货地址共享,是指用户在微信浏览器内打开网页,填写过地址后,后续可以免填写支持快速选择,也可增加和编辑.此地址为用户属性,可在各商户的网页中共享使用.支持原生控件填写地址,地址数据会传递到商户. 地址共享是基于微信JavaScript API 实现,只能在微信内置浏览器中使用,其他浏览器调用无效

wex5实战之管理收货地址(二)

接着上一张管理收货地址,这章主要讲解新增,编辑,选择省市区功能,主要有windowReceiver.windowDialog.tree组件的使用. 1.新增.编辑地址,页面. 在页面中放入windowReceiver.windowDialog组件 windowReceiver:用于接收地址参数,判断是否为新增或编辑. windowDialog:用于打开选择省市区弹窗,返回选择数据. Model.prototype.windowReceiver1Receive = function(event){