DRF实操学习——收货地址的设计

news2024/9/27 13:34:01

DRF实操学习——收货地址的设计

  • 1.行政区划表的设计
  • 2. 行政区划表接口演示
    • 1.返回所有的省份
    • 2. 查询指定上级行政区划的所有子区划,以及展示自身区划
  • 3.行政区划表接口重写
  • 补充:前端请求逻辑
  • 4. 优化
  • 5.收货地址的设计
  • 6. 收货地址表接口重写
  • 7.优化
    • 1. 优化返回的数据
    • 2.增加额外的校验,重写 validate_<field_name> 方法

分析:

  1. 提供收货地址的选择:提供行政区划的三级联动查询,省——市——区
  2. 完成用户保存添加的收货地址

1.行政区划表的设计

在这里插入图片描述

  1. 在users的models中增加模型类Area,然后迁移映射
# 行政区划表
class Area(models.Model):
    name = models.CharField(max_length=20,verbose_name='名称')
    # 'self'建立外键关联自身主键。添加的上级行政区划必须是行政区划表中已有的数据
    # 省份没有上级行政区划 on_delete=models.SET_NULL删除时设置为空,null=True允许为空
    # blank=True,
    parent = models.ForeignKey('self',on_delete=models.SET_NULL,null=True,blank=True,verbose_name='上级行政区划')

    class Meta:
        db_table = 'area'
        verbose_name = '行政区划'
        verbose_name_plural = verbose_name
  1. 将省份等行政区划的基础数据配置进去
    在这里插入图片描述
  2. 编写序列化器
class AreaSerializer(ModelSerializer):
    class Meta:
        model = Area
        fields = ['id','name']
  1. 编写视图
class AreaViewSet(ModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer
  1. 增加路由
from django.urls import path
from rest_framework.routers import DefaultRouter
from rest_framework_jwt.views import obtain_jwt_token
from .views import *

urlpatterns = [
    path('login/', obtain_jwt_token),
    path('image/verification/<uuid:uuid>/', ImageVerifyView.as_view())
]
router = DefaultRouter()
router.register('users', UserViewSet)
router.register('area', AreaViewSet)
urlpatterns += router.urls

2. 行政区划表接口演示

分析:
把查询划分为两个接口

  1. 得到所有的省份:修改list视图函数,返回所有省份
  2. 把省份的id传入,修改详情路由,查询指定上级行政区划的所有子区划,以及展示自身区划

1.返回所有的省份

重写get_queryset方法,当操作为list操作时,查询所有parent=None的数据,即省份

class AreaViewSet(ModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer

    def get_queryset(self):
        if self.action == 'list':
        	#查询所有parent=None的数据,即省份
            return Area.objects.filter(parent=None)
        else:
            return self.queryset

2. 查询指定上级行政区划的所有子区划,以及展示自身区划

  1. 优化返回结果,修改序列化器
# 行政区划序列化器
class AreaSerializer(ModelSerializer):
    """行政区划自身序列化器"""
    class Meta:
        model = Area
        fields = ['id','name']

# 增加一个新的行政区划的序列化器
class ParentSerializer(ModelSerializer):
    """
    行政区划自身序列化器及子级区划
    """
    # parent时外键关联自身,Area表时一对多查询
    # 生成管理器:源模型类名小写_set。通过管理器获取源模型类的所有数据
    area_set = AreaSerializer(many=True,read_only=True)
    class Meta:
        model = Area
        fields = ['id','name','area_set']

  1. 重写get_serializer_class
class AreaViewSet(ModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer

    def get_queryset(self):
        if self.action == 'list':
            # 查询所有parent=None的数据,即省份
            return Area.objects.filter(parent=None)
        else:
            return self.queryset

    # get_serializer返回的是对象,get_serializer_class返回的是类
    # 重写get_serializer或get_serializer_class都可以
    def get_serializer_class(self):
        if self.action == 'retrive':
            #省份
            return ParentSerializer 
        else:
            return AreaSerializer

接口验证如下:
在这里插入图片描述

3.行政区划表接口重写

重写create、update、destroy方法

    @wrap_permisssion(RootPermission)#修改权限为root用户
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permisssion(RootPermission)#修改权限为root用户
    def update(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permisssion(RootPermission)#修改权限为root用户
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

补充:前端请求逻辑

在这里插入图片描述
选择省份的输入框,会向后端发送请求,获取所有省份,渲染到前端。比如选择湖北省,然后前端获取到湖北省的id,再次向后端发起请求,获取到湖北省下的所有区划。同理,在根据孝感市的id获取到孝感市下的所有区划。

4. 优化

分析:
特点:增加、删除、修改、更新操作少。查询操作多。
所以可以增加缓存功能,因为msyql性能相对来收比较慢,主要是做持久化数据。redis相当于是内存,高速读取数据库。可以将查询操作多的数据放在redis中,即将高频数据或临时数据缓存。

  1. 下载第三方库drf-extensions
    在这里插入图片描述

  2. 在settings中新增一个缓存配置
    在这里插入图片描述
    在这里插入图片描述

  3. 优化视图

from rest_framework_extensions.cache.mixins import CacheResponseMixin

#继承CacheResponseMixin,那么该视图下的所有操作都会缓存到area库中
class AreaViewSet(CacheResponseMixin, ModelViewSet):
    queryset = Area.objects.all()
    serializer_class = AreaSerializer


  1. 发送查询请求后,查看redis的4号库,可以查看到数据,后续查询该数据时,会现在redis中查询数据是否存在,存在则直接返回,不存在,则去数据库中查询,然后再缓存在redis中
    在这里插入图片描述
    在这里插入图片描述

5.收货地址的设计

分析:
一个用户可以有多个收货地址:一对多关系。
定义收货地址模型类 ,新建一个收货地址表,外键关联用户表,保存是哪个用户创建的。

  1. 在users的models中增加模型类Address,然后迁移映射
# 行政区划表
class Address(ModelSetMixin):
    name = models.CharField(max_length=40,verbose_name='地址名')
    receiver = models.CharField(max_length=40,verbose_name='收货人')
    # on_delete=models.PROTECT受保护的,防止删除与该外键相关联的对象
    # 这里都关联了Area表,管理器都是area_set,管理器冲突,因此要重命名管理器名
    province = models.ForeignKey(Area,on_delete=models.PROTECT,verbose_name='省',related_name='province_address')
    city = models.ForeignKey(Area,on_delete=models.PROTECT,verbose_name='市',related_name='city_address')
    district = models.ForeignKey(Area,on_delete=models.PROTECT,verbose_name='区',related_name='district_address')
    place = models.CharField(max_length=40,verbose_name='详情地址')
    mobile = models.CharField(max_length=11,verbose_name='手机')

    user = models.ForeignKey(User,on_delete=models.CASCADE,verbose_name='用户')

    class Meta:
        ordering = ['-update_time']
        db_table = 'adress'
        verbose_name = '收货地址'
        verbose_name_plural = verbose_name
  1. 创建序列化器
class AddressSerializer(ModelSerializer):
    class Meta:
        model = Address
        exclude = ['is_delete']

  1. 编写视图
    分析:
    创建:当前登录用户
    修改:当前登录用户
    删除:当前登录用户
    查询:当前登录用户
    查询详情:当前登录用户
    所以我们可以对查询集进行处理
class AddressViewSet(ModelViewSet):
    queryset = Address.objects.all()
    serializer_class = AddressSerializer
    permission_classes = [IsAuthenticated]

    def get_queryset(self):
    	# 之前是判断有没有权限,可以返回数据
        # 这里直接只能返回该用户的数据,爬虫无法找到
        return self.request.user.address_set.filter(is_delete=False)

补充另一种写法:
不在视图中写queryset
在这里插入图片描述

则需要在路由中补充basename
在这里插入图片描述

  1. 增加路由
from django.urls import path
from rest_framework.routers import DefaultRouter
from rest_framework_jwt.views import obtain_jwt_token
from .views import *

urlpatterns = [
    path('login/', obtain_jwt_token),
    path('image/verification/<uuid:uuid>/', ImageVerifyView.as_view())
]
router = DefaultRouter()
router.register('users', UserViewSet)
router.register('area', AreaViewSet)
# 如果在AddressViewSet不写queryset,则需要在路由中
# 增加basename,指定模型类
router.register('address', AddressViewSet, basename='address')
urlpatterns += router.urls

6. 收货地址表接口重写

	@auto_user
    def create(self, request, *args, **kwargs):
        max_count = 3
        if self.get_queryset().count() >= max_count:
            return Response({'detail':f'收货地址数量超过{max_count}条上限'},status=HTTP_400_BAD_REQUEST)
        return ModelViewSet.create(self, request, *args, **kwargs)


    @update_auto_user
    def update(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @destory_auto_user
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

7.优化

1. 优化返回的数据

在这里插入图片描述
修改序列化器

class AddressSerializer(ModelSerializer):
    province_name = serializers.CharField(source='province.name',read_only=True)
    city_name = serializers.CharField(source='city.name',read_only=True)
    district_name = serializers.CharField(source='district.name',read_only=True)
    class Meta:
        model = Address
        exclude = ['is_delete']

查询结果如下:
在这里插入图片描述

2.增加额外的校验,重写 validate_<field_name> 方法

字段级别的校验

from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *
import re

class AddressSerializer(ModelSerializer):
    province_name = serializers.CharField(source='province.name',read_only=True)
    city_name = serializers.CharField(source='city.name',read_only=True)
    district_name = serializers.CharField(source='district.name',read_only=True)
    class Meta:
        model = Address
        exclude = ['is_delete']


    #自定义校验器,增加额外的校验功能:重写 validate_<field_name> 方法,字段级别的校验
    # 对手机号码进行校验
    def validate_mobile(self,value):
        if not re.match(r'1[3-9]\d{9}$',value):
            raise serializers.ValidationError('手机号码格式错误')
        return value

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170116.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 12系统源码_输入系统(三)输入事件的加工和分发

前言 上一篇文章我们具体分析了InputManagerService的构造方法和start方法&#xff0c;知道IMS的start方法经过层层调用&#xff0c;最终会触发Navite层InputDispatcher的start方法和InputReader的start方法。InputDispatcher的start方法会启动一个名为InputDispatcher的线程&…

混拨动态IP代理的优势是什么

在当今互联网时代&#xff0c;隐私保护和网络安全成为了人们关注的焦点。无论是个人用户还是企业&#xff0c;都希望能够在网络上自由、安全地进行各种活动。混拨动态IP代理作为一种新兴的技术手段&#xff0c;正逐渐受到大家的青睐。那么&#xff0c;混拨动态IP代理到底有哪些…

【工具】JDK版本不好管理,SDKMAN来帮你

前言 &#x1f34a;缘由 SDKMAN真是好&#xff0c;JDK切换没烦恼 &#x1f423; 闪亮主角 大家好&#xff0c;我是JavaDog程序狗 今天跟大家能分享一个JDK版本管理工具SDKMAN 当你同时使用JDK 1.8的和JDK 17并行维护两个项目时。每次在两个项目之间并行开发&#xff0c;切…

进阶数据库系列(十三):PostgreSQL 分区分表

概述 在组件开发迭代的过程中&#xff0c;随着使用时间的增加&#xff0c;数据库中的数据量也不断增加&#xff0c;因此数据库查询越来越慢。 通常加速数据库的方法很多&#xff0c;如添加特定的索引&#xff0c;将日志目录换到单独的磁盘分区&#xff0c;调整数据库引擎的参…

2.4卷积3

2.4卷积3 文章学习自https://zhuanlan.zhihu.com/p/41609577&#xff0c;详细细节请读原文。 狄拉克 δ \delta δ 函数&#xff1a; δ ( x ) { ∞ , x 0 0 , x ≠ 0 \delta (x){\begin{cases} \infty ,& x0\\ 0,& x\neq 0\end{cases}} δ(x){∞,0,​x0x0​ 并…

小柴冲刺软考中级嵌入式系统设计师系列二、嵌入式系统硬件基础知识(2)嵌入式微处理器基础

目录 冯诺依曼结构 哈佛结构 一、嵌入式微处理器的结构和类型 1、8位、16位、32位处理器的体系结构特点 2、DSP处理器的体系结构特点 3、多核处理器的体系结构特点 二、嵌入式微处理器的异常与中断 1、异常 2、中断 flechazohttps://www.zhihu.com/people/jiu_sheng …

54 循环神经网络RNN_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录循环神经网络使用循环神经网络的语言模型困惑度&#xff08;perplexity&#xff09;梯度剪裁 循环神经网络 使用循环神经网络的语言模型 输入“你”&#xff0c;更新隐变量&#xff0c;输出“好”。 困惑度&#xff08;perplexity&#xff…

【递归】8. leetcode 671 二叉树中第二小的节点

题目描述 题目链接&#xff1a;二叉树中第二小的节点 2 解答思路 注意这句话&#xff1a;该节点的值等于两个子节点中较小的一个 二叉树的根节点的值是整棵树中最小的值 本道题所要求的是二叉树中第二小的节点。因为根节点是最小的节点&#xff0c;那么我们只需要找到第一…

HT5169内置BOOST升压的11W I2S输入D类音频功放

1 特性 ● 电源供电 升压输入VBAT:2.5V-5.5V; 升压输出PVDD可调&#xff0c;最高7.5V DVDD/AVDD分辨率:3.3V ● 音频性能 9.0W (VBAT3.7V, PVDD 7.5V, RL3Ω.THDN10%) 11.0W(VBAT3.7V, PVDD 7.5V, RL2Ω.THDN10% 5.5W (VBAT3.7V, PVDD 6.5V, RL4Ω.THDN10%) ● 灵活的…

红米k60至尊版工程固件 MTK芯片 资源预览 刷写说明 与nv损坏修复去除电阻图示

红米k60至尊版机型代码为:corot。 搭载了联发科天玑9200+处理器。此固件mtk引导为MT6985。博文将简单说明此固件的一些特点与刷写注意事项。对于NV损坏的机型。展示修改校验电阻的图示。方便改写参数等 通过博文了解 1💝💝💝-----此机型工程固件的资源刷写注意事项 2…

css 中 ~ 符号、text-indent、ellipsis、ellipsis-2、text-overflow: ellipsis的使用

1、~的使用直接看代码 <script setup> </script><template><div class"container"><p><a href"javascript:;">纪检委</a><a href"javascript:;">中介为</a><a href"javascript:…

曲线图异常波形检测系统源码分享

曲线图异常波形检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Comput…

【cache】浅析四种常用的缓存淘汰算法 FIFO/LRU/LFU/W-TinyLFU

本文浅析淘汰策略与工作中结合使用、选取&#xff0c;并非针对算法本身如何实现的 文章目录 FIFOLFULRUW-TinyLFU实践与优化监控与调整 FIFO first input first output &#xff0c; 先进先出&#xff0c;即最早存入的元素最先取出&#xff0c; 典型数据结构代表&#xff1a;…

SpringCloud-Netflix第一代微服务快速入门

1.springCloud常用组件 Netflix Eureka 当我们的微服务过多的时候&#xff0c;管理服务的通信地址是一个非常麻烦的事情&#xff0c;Eureka就是用来管理微服务的通信地址清单的&#xff0c;有了Eureka之后我们通过服务的名字就能实现服务的调用。 Netflix Ribbon\Feign : 客…

Python精选200Tips:171-175

深度学习实战项目 P171--CIFAR10数据集图像分类(Image Classification)P172--MS COCO数据集物体检测(Object Detection)P173-- MNIST手写数字数据集DCGAN生成P174--基于EasyOCR的字符识别P175--基于Air Quality数据集的变分自编码器(Variational autoEncoder&#xff0c;VAE) 运…

QT版数据采集系统研发过程记录

研发目的&#xff1a;通过智能监测设备将各个变电站运行的电压、电流、温湿度等数据采集汇总到计算机中心服务器&#xff0c;通过系统软件展示各个站点对应的运行工况。 软件架构&#xff1a;使用QT开发跨平台&#xff08;Windows系统、Ubuntu20.04&#xff09;客户端软件、连…

基于MATLAB的苹果外观特征检测

摘 要 本文根据苹果分级判定标准中的两个评定指标&#xff1a;果径和果面缺陷&#xff0c;探讨如何利用MATLAB技术进行苹果外观的特征检测&#xff0c;从而提高苹果品质检测的工作效率。 关键词 MATLAB&#xff1b;苹果分级&#xff1b;果径&#xff1b;果面缺陷 0 引言 …

Pandas -----------------------基础知识(四)

自定义函数 Series 加载数据 import pandas as pd df pd.DataFrame({Age: [20, 25, 30, 35, 40]}) df # 目标: 让 Age 列 的每个元素 num1 num2 def add_nums(x,num1,num2):return x num1 num2 df[Age].apply(add_nums,num1 2,num2 3) 法二 df[Age].apply(lambda x ,num1…

大模型算法入行转行?指南来了!

最近私信问我关于入行、转行方面的问题比较多&#xff0c;就专门写一篇讲讲我的理解。 首先说明一下个人的背景和现状&#xff0c;我本人是本科学历&#xff0c;有互联网大厂搜推方向经验&#xff0c;后来跳到中厂继续做推荐&#xff0c;去年开始做大模型。现在是个小组长&…

用ChatGPT做数据分析与挖掘,爽!

导读&#xff1a;在现代数据分析中&#xff0c;Python凭借其强大的数据处理能力和丰富的库资源成为首选工具。ChatGPT&#xff0c;作为先进的自然语言处理模型&#xff0c;正逐步成为Python数据分析与挖掘的强大辅助工具。 通过ChatGPT的自然语言处理能力&#xff0c;用户可以…