当前位置: 首页> 健康> 美食 > 全球疫情实时播报_360建筑网 诚是什么意思_搜索引擎优化介绍_网站快速排名服务

全球疫情实时播报_360建筑网 诚是什么意思_搜索引擎优化介绍_网站快速排名服务

时间:2025/7/9 6:46:52来源:https://blog.csdn.net/m0_51453764/article/details/142524307 浏览次数:0次
全球疫情实时播报_360建筑网 诚是什么意思_搜索引擎优化介绍_网站快速排名服务

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 = Areafields = ['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 = AreaSerializerdef 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 = Areafields = ['id','name']# 增加一个新的行政区划的序列化器
class ParentSerializer(ModelSerializer):"""行政区划自身序列化器及子级区划"""# parent时外键关联自身,Area表时一对多查询# 生成管理器:源模型类名小写_set。通过管理器获取源模型类的所有数据area_set = AreaSerializer(many=True,read_only=True)class Meta:model = Areafields = ['id','name','area_set']
  1. 重写get_serializer_class
class AreaViewSet(ModelViewSet):queryset = Area.objects.all()serializer_class = AreaSerializerdef 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 = Addressexclude = ['is_delete']
  1. 编写视图
    分析:
    创建:当前登录用户
    修改:当前登录用户
    删除:当前登录用户
    查询:当前登录用户
    查询详情:当前登录用户
    所以我们可以对查询集进行处理
class AddressViewSet(ModelViewSet):queryset = Address.objects.all()serializer_class = AddressSerializerpermission_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_userdef create(self, request, *args, **kwargs):max_count = 3if 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_userdef update(self, request, *args, **kwargs):return ModelViewSet.create(self, request, *args, **kwargs)@destory_auto_userdef 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 = Addressexclude = ['is_delete']

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

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

字段级别的校验

from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *
import reclass 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 = Addressexclude = ['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
关键字:全球疫情实时播报_360建筑网 诚是什么意思_搜索引擎优化介绍_网站快速排名服务

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: