DRF实操学习——商城

news2024/9/29 14:15:16

DRF实操学习——商城

  • 1. 商城模型的设计
  • 2. 优化
    • 商品分类表
      • 1. 序列化器和查询集的优化
      • 2. 得到指定类目的所有商品
    • 商品表
      • 1. 视图的基础权限等配置
      • 2. 增加上传商品图片的接口
      • 3. 优选商品接口

分析:

  1. 商品分类表
  2. 商品表
  3. 商品图片表:一个商品有多张图片

1. 商城模型的设计

  1. 新建一个shopping的app
    在这里插入图片描述

  2. 在settings中注册该app
    在这里插入图片描述

  3. 创建模型,迁移映射

from django.db import models

from utils.modelsMixin import ModelSetMixin


# 商品分类表
class Classification(ModelSetMixin):
    name = models.CharField(max_length=40,verbose_name='分类名')
    # models.SET_NULL如果上级分类被删了,设置为空。外键关联自身
    parent = models.ForeignKey('self',on_delete=models.SET_NULL,null=True,blank=True,verbose_name='上级分类')

    class Meta:
        db_table = 'classification'
        verbose_name = '商品分类'
        verbose_name_plural = verbose_name

	def __str__(self):
        return f'%s.%s' % (self.id,self.name)

# 商品表
class Commodity(ModelSetMixin):
    STATUS_CHOICES = (
        (0,'未发布'),
        (1,'发布'),
    )
    name = models.CharField(max_length=40,verbose_name='商品名')
    caption = models.CharField(max_length=40,verbose_name='副标题')
    brand = models.CharField(max_length=40,verbose_name='品牌',null=True,blank=True)
    # 注:FloatField有计算精度的问题,如果有小数且参与计算,用DecimalField
    # 如果有小数,但是不怎么参与计算,那么可以使用FloatField
    # max_digits最大的位数 decimal_places小数为的最大位数
    price = models.DecimalField(max_digits=10,decimal_places=2,verbose_name='单价')
    stock = models.IntergerField(verbose_name='库存')
    pack = models.TextField(verbose_name='包装信息',null=True,blank=True)
    serviceafter_sale = models.TextField(verbose_name='售后服务',null=True,blank=True)
    sales = models.IntergerField(verbose_name='销量',default=0)
    comments = models.IntergerField(verbose_name='评价数',default=0)
    status = models.IntergerField(verbose_name='状态',default=0,choices=STATUS_CHOICES)
    detail = models.TextField(verbose_name='详情',null=True,blank=True)

    classification1 = models.ForeignKey(Classification,on_delete=models.PROTECT,verbose_name='一级分类',related_name='一级分类')
    classification2 = models.ForeignKey(Classification,on_delete=models.PROTECT,verbose_name='二级分类',related_name='二级分类')
  
    class Meta:
        ordering=['-sales','-comments','-create_time']
        db_table = 'commodity'
        verbose_name = '商品'
        verbose_name_plural = verbose_name


# 商品图片表
class CommodityImg(models.Model):
    src = models.TextField(verbose_name='图片地址')
    priority = models.IntegerField(default=0,verbose_name='优先级')
    commodity = models.ForeignKey(Commodity,on_delete=models.CASCADE,verbose_name='商品')

    class Meta:
        ordering=['-priority','-id']
        db_table = 'commodity_img'
        verbose_name = '商品图'
        verbose_name_plural = verbose_name


  1. 创建序列化器
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *


class ClassificationSerializer(ModelSerializer):
    class Meta:
        model = Classification
        exclude = ['is_delete']

class CommoditySerializer(ModelSerializer):
    class Meta:
        model = Commodity
        exclude = ['is_delete']

class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = '__all__'

  1. 创建视图
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from .serializers import *

class ClassificationViewSet(ModelViewSet):
    queryset = Classification.objects.filter(is_delete=False)
    serializer_class = ClassificationSerializer

class CommodityViewSet(ModelViewSet):
    queryset = Commodity.objects.filter(is_delete=False)
    serializer_class = CommoditySerializer

class CommodityImgViewSet(ModelViewSet):
    queryset = CommodityImg.objects.filter(is_delete=False)
    serializer_class = CommodityImgSerializer
  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 = []
router = DefaultRouter()
router.register('classifications', ClassificationViewSet)
router.register('commodity', CommodityViewSet)
router.register('commodity_img', CommodityImgViewSet)
urlpatterns += router.urls
  1. 增加主路由
from django.contrib import admin
from django.urls import path, include
from rest_framework.documentation import include_docs_urls

urlpatterns = [
    path('admin/', admin.site.urls),
    path('drfstudy/', include('drfstudy.urls')),
    path('users/', include('users.urls')),
    path('school/', include('school.urls')),
    path('work/', include('work.urls')),
    path('community/', include('community.urls')),
    path('shopping/', include('shopping.urls')),
    path('docs/', include_docs_urls('DRF6项目接口文档'))  # 配置接口文档路由地址,文档标题
]

2. 优化

商品分类表

1. 序列化器和查询集的优化

  1. 序列化器的优化
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *


class ClassificationSerializer(ModelSerializer):
    class Meta:
        model = Classification
        exclude = ['is_delete']

class ParentClassificationSerializer(ModelSerializer):
    # 要把子集展示出来,使用管理器。源模型小写_set
    classification_set = ClassificationSerializer(many=True,read_only=True)

    class Meta:
        model = Classification
        exclude = ['is_delete']

  1. 查询集的优化
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from .serializers import *

class ClassificationViewSet(ModelViewSet):
    queryset = Classification.objects.filter(is_delete=False,parent=None)
    serializer_class = ParentClassificationSerializer

  1. 查询结果如下
    在这里插入图片描述
  2. 优化查询结果,继续修改序列化器
from rest_framework.serializers import ModelSerializer
from rest_framework import serializers
from .models import *


class ClassificationSerializer(ModelSerializer):
    class Meta:
        model = Classification
        fields = ['id','name']

class ParentClassificationSerializer(ModelSerializer):
    # 要把子集展示出来,使用管理器。源模型小写_set
    classification_set = ClassificationSerializer(many=True,read_only=True)

    class Meta:
        model = Classification
        fields = ['id','name','classification_set','parent']

        # 更改属性
        extra_kwargs = {
            # 将parent字段设置为只写,无法查看
            'parent':{'write_only':True} 
        }

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

  1. 增加权限
from django.shortcuts import render
from rest_framework.viewsets import ModelViewSet
from .serializers import *
from rest_framework.permissions import IsAuthenticated

class ClassificationViewSet(ModelViewSet):
    queryset = Classification.objects.filter(is_delete=False,parent=None)
    serializer_class = ParentClassificationSerializer
    permission_classes = [IsAuthenticated]

    #更改权限装饰器,只有老师才有权限创建
    @wrap_permisssion(TeacherPermission) 
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)

    @wrap_permisssion(TeacherPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permisssion(TeacherPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

2. 得到指定类目的所有商品

在ClassificationViewSet中增加以下接口

    @action(methods=['get'],detail=True)
    def commodity(self,request,pk):
        try:
            classification = Classification.objects.filter(is_delete=False).get(id=pk)
        except Classification.DoesNotExist:
            return response(status=HTTP_404_NOT_FOUND)
        # 得到这个类目的所有商品,使用管理器
        # 判断类目是顶层类目还是子类目
        # 默认为顶层类目
        classification_attr = 'classification1'
        # 顶层类目 展示自身类目名
        classification_name = classification.name 
        if classification.parent:
            classification_attr = 'classification2'
            classification_name =  f'{classification.parent.name}---{classification.name}'
        # 使用内置函数getattr获取属性
        data = getattr(classification,classification_attr).filter(is_delete=False,status=1)
        return Response({
            'classification':classification_name,
            'commodity':CommoditySerializer(data,many=True).data
        })

商品表

1. 视图的基础权限等配置

class CommodityViewSet(ModelViewSet):
    queryset = Commodity.objects.filter(is_delete=False)
    serializer_class = CommoditySerializer
    permission_classes = [IsAuthenticated]

    # 重写get_queryset方法的场景:根据不同的操作场景设置不同的查询集
    def get_queryset(self):
        if self.action in ['list','retrieve']: #如果是查询,则只能返回已发布的商品
            return Commodity.objects.filter(is_delete=False,status=1)
        return self.queryset
    
    #更改权限装饰器,只有老师才有权限创建
    @wrap_permisssion(TeacherPermission) 
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)
 
    @wrap_permisssion(TeacherPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permisssion(TeacherPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

2. 增加上传商品图片的接口

from config.fastdfsConfig import FASTDFS_SERVER_DOMAIN
from fdfs_client.client import Fdfs_client, get_tracker_conf
import logging
# 导入日志器
logger = logging.getLogger(__name__)

# 创建FastDFS客户端对象
tracker_path = get_tracker_conf('utils/fastdfs/client.conf')
client = Fdfs_client(tracker_path)

class CommodityViewSet(ModelViewSet):
    queryset = Commodity.objects.filter(is_delete=False)
    serializer_class = CommoditySerializer
    permission_classes = [IsAuthenticated]

    # 重写get_queryset方法的场景:根据不同的操作场景设置不同的查询集
    def get_queryset(self):
        if self.action in ['list','retrieve']: #如果是查询,则只能返回已发布的商品
            return Commodity.objects.filter(is_delete=False,status=1)
        return self.queryset
    
    #更改权限装饰器,只有老师才有权限创建
    @wrap_permisssion(TeacherPermission) 
    def create(self, request, *args, **kwargs):
        return ModelViewSet.create(self, request, *args, **kwargs)
 
    @wrap_permisssion(TeacherPermission)
    def update(self, request, *args, **kwargs):
        return ModelViewSet.update(self, request, *args, **kwargs)

    @wrap_permisssion(TeacherPermission)
    def destroy(self, request, *args, **kwargs):
        return ModelViewSet.destroy(self, request, *args, **kwargs)

    @action(methods=['post'],detail=True)
    def img(self,request,pk):
        """
        上传图片
        """
        #获取商品
        try:
            commodity = self.get_queryset().get(id=pk)
        except Commodity.DoesNotExist:
            return Response(status=HTTP_404_NOT_FOUND)
        # 上传图片
        # 得到上传的文件数据
        file = request.FILES.get('file')
        # 判断是否有图片数据,文件类型是否是图片
        if not file or file.content_type not in ('image/jpeg', 'image/png', 'image/gif'):
            # 不是,返回客户端传入数据错误
            return Response(status=HTTP_400_BAD_REQUEST)

        # 是,交给fastdfs,存储到可用的storage服务上
        # 得到文件后缀名,如果没有后缀名则默认为png类型
        try:
            images_ext_name = file.name.split('.')[-1]
        except Exception as e:
            logger.info('图片拓展名异常:%s' % e)
            images_ext_name = 'png'

        # 上传图片数据,通过字节流
        try:
            upload_res = client.upload_by_buffer(file.read(), file_ext_name=images_ext_name)
        except Exception as e:
            logger.error('图片上传出现异常:%s' % e)
            return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)
        else:
            if upload_res.get('Status') != 'Upload successed.':
                logger.warning('图片上传失败')
                return Response(status=HTTP_500_INTERNAL_SERVER_ERROR)

            # 得到返回的file_id
            image_name = upload_res.get('Remote file_id').decode()
            image_url = FASTDFS_SERVER_DOMAIN + image_name

            #保存图片地址
            CommodityImg.objects.create(src=image_url,commodity = commodity)

            #返回
            return Response({'data':image_url})

修改序列化器,优化查询结果

class CommodityImgSerializer(ModelSerializer):
    class Meta:
        model = CommodityImg
        fields = ['src']

class CommoditySerializer(ModelSerializer):
    # classification1是外键关联的Classification表
    classification1_name = serializers.CharField(source='classification1.name',read_only=True)
    classification2_name = serializers.CharField(source='classification2.name',read_only=True)
    # 添加管理器:类名小写_set
    commodityimg_set = CommodityImgSerializer(many=True,read_only=True)
    class Meta:
        model = Commodity
        exclude = ['is_delete']

优化后的查询结果如下:

在这里插入图片描述

3. 优选商品接口

在CommodityViewSet视图中增加以下接口

    @action(methods=['get'],detail=False)
    def optimization(self,request):
        """
        优选商品接口,返回评论数最多的前五个商品
        """
        # 这里使用order_by会覆盖在模型中使用的order_by
        queryset = self.get_queryset().order_by('-comments').order_by('-create_time')
        # 使用切片返回前五条数据:0,1,2,3,4
        return Response(self.get_serializer(queryset[:5],many=True).data)

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

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

相关文章

(undone) MIT6.824 Lab1

参考:http://nil.csail.mit.edu/6.824/2021/labs/lab-mr.html task1: 熟悉讲义,尤其是搞明白如何运行测试程序(完成) ------------------------------------------------ start 先看 Introduction 我们的目标:构建一个MapReduce系统。 细节&…

数据结构_2.2、顺序表插入删除查找

1、线性表的顺序存储表示定义: 线性表:是具有相同数据类型的n (n≥0)个数据元素的有限序列 顺序表:用顺序存储的方式实现线性表 顺序存储:把逻辑上相邻的元素存储在物理 位置上也相邻的存储单元中&#…

前端大模型入门:实战篇之Vue3+Antdv+transformers+本地模型实现增强搜索

本文将之前的文章,实现一个场景的实战应用,包含代码等内容。利用纯前端实现增强的列表搜索,抛弃字符串匹配,目标是使用番茄关键字可以搜索到西红柿 1 准备工作 1.1 了解llm和web开发 web端的ai开发参考 前端大模型入门&#xff…

MPI程序实例:数值积分(π值计算)

目录 一、算法介绍 二、代码实现 一、算法介绍 本程序实例通过下面的公司计算定积分的近似值: (1) 其中为积分区间数,为积分步长,为积分区间的中点,被积函数。 假设总进程数为p(程序中的numprocs变量)&a…

判断JDK是否包含某个class

问题描述:今天遇到个问题,把oracle替换为openjdk,应用启动时,提示noclassdeffounderror 解决办法:先确认下环境里的jdk里是否包含这个class,进入jdk安装目录的/jre/lib,执行命令:ja…

tar命令:压缩、解压的好工具

一、命令简介 用途: tar​ 命令用于创建归档文件(tarball),以及从归档文件中提取文件。 标签: 文件管理,归档。 特点: 归档文件可以保留原始文件和目录的层次结构,通常使用 .tar ​…

每日OJ题_牛客_HJ108求最小公倍数_C++_Java

目录 牛客_HJ108求最小公倍数_C_Java 题目解析 C代码 Java代码 牛客_HJ108求最小公倍数_C_Java 求最小公倍数_牛客题霸_牛客网 题目解析 A 和 B 的最小公倍数 A * B / 两者的最大公约数。最大公约数&#xff1a;辗转相除法。 C代码 #include <iostream> #includ…

C语言—顺序表(含通讯录项目)

目录 一、顺序表的概念及结构 二、顺序表的分类 &#xff08;2.1&#xff09;静态顺序表 &#xff08;2.2&#xff09;动态顺序表 三、动态顺序表的实现 &#xff08;3.1&#xff09;基本结构定义 &#xff08;3.2&#xff09;初始化和销毁 &#xff08;3.2.1&#xff0…

【MWORKS专业工具箱系列教程】控制系列工具箱第四期:时域分析

本工具箱教程以控制系统模型创建、分析与设计流程为主线&#xff0c;通过大量示例介绍MWORKS控制系统工具箱的功能和具体使用。共计10篇文章&#xff0c;上一篇主要介绍了控制系统连接与化简。 同元软控&#xff1a;【MWORKS专业工具箱系列教程】控制系 列工具箱第三期&#x…

Shopline对接需要注意的问题

Shopline对接是一项复杂而细致的工作&#xff0c;为了确保对接的顺利进行&#xff0c;并保证系统的稳定性和可靠性&#xff0c;需要注意以下几个方面。 1.API文档的详细阅读 功能理解&#xff1a; 仔细阅读Shopline提供的API文档&#xff0c;全面了解每个接口的功能、参数、返…

一起发现CMake太美-01-CMake是什么CMake的前世今生

本系列课程的主要内容包括&#xff1a; 点击本课程的 链接 可以进入视频课程的学习。 下面介绍本系列课程的第一课的主要内容&#xff0c;本节课从CMake是什么&#xff0c;能做什么&#xff0c;以及CMake的远亲近邻入手&#xff0c;让大家对CMake有一个大致的了解。 随后&am…

SpringBoot+MyBatisPlus实现多数据源动态切换

场景&#xff1a; 假设有一个项目&#xff0c;产品数据存放在new数据库中&#xff0c;公告信息存放在mini数据库中&#xff0c;我们要怎么去查询两个数据库中不同的数据呢&#xff1f; 这个时候我们就要用到mybatisplus提供的多数据源&#xff0c;仅需要如下配置即可实现相关…

【C语言从不挂科到高绩点】24-C语言中的枚举【重点知识】

Hello!彦祖们,俺又回来了!!!,继续给大家分享 《C语言从不挂科到高绩点》课程!! 本节将为大家讲解C语言中非常重要的知识点-枚举: 本套课程将会从0基础讲解C语言核心技术,适合人群: 大学中开设了C语言课程的同学想要专升本或者考研的同学想要考计算机等级证书的同学想…

Anzo Capital昂首资本官网:掌握止损单的艺术,优化交易策略

通过在Anzo Capital昂首资本官网的深入研究&#xff0c;投资者发现宝贵的交易策略&#xff0c;尤其是在市场不活跃的时期&#xff0c;止损单的触发时机往往相当微妙。很多时候&#xff0c;主力的动作似乎开始得更晚&#xff0c;这种情况在交易市场中并不罕见。尽管没有人能够确…

【数据库文档】数据库设计说明书(Word原件参考)

一、 总述 &#xff08;一&#xff09; 编写目的 二、 外部设计 &#xff08;一&#xff09; 环境说明 &#xff08;二&#xff09; 指导 三、 物理实现 &#xff08;一&#xff09; 物理结构 &#xff08;二&#xff09; 安全设计 四、 表设计结构 &#xff08;一&#xff09;…

AutoGen实现多代理—AI Agentic Design Patterns with AutoGen(二)

1. AutoGen顺序对话在客户入职案例上的应用 如图&#xff0c;客户入职前会经历三个阶段&#xff0c;一个代理收集客户的信息&#xff0c;一个代理收集客户的感兴趣话题&#xff0c;一个代理根据前两个代理的基础信息与客户代理对话&#xff0c;产生聊天信息。 本节实验的地址&…

基于SSM+小程序的会议发布与预约管理系统(会议1)(源码+sql脚本+视频导入教程+文档)

&#x1f449;文末查看项目功能视频演示获取源码sql脚本视频导入教程视频 1、项目介绍 本基于微信小程序的会议发布与预约系统管理员功能有个人中心&#xff0c;发布者管理&#xff0c;用户管理&#xff0c;发布会议管理&#xff0c;会议预约管理&#xff0c;留言板管理&…

C++远端开发环境手动编译安装(centos7)

背景 直接使用yum安装&#xff0c;无法安装指定的版本&#xff0c;因为很多版本并没有在镜像仓库中&#xff0c;所以此处进行手动安装指定版本 使用VMWare安装centos7 准备centos镜像 可以自行搜索下载地址&#xff0c;阿里云的也可以 下载VmWare&#xff0c;社区版即可 可…

【第十四周】PyTorch深度学习实践1

目录 摘要Abstract1.反向传播2.线性回归2.1.准备数据集2.2.设计模型2.3.定义损失函数和优化器2.4.模型训练 3.逻辑回归4.处理多维特征的输入5.加载数据集5.1.导入必要的库5.2.准备数据集5.3.定义模型5.4.构建损失函数和优化器5.5.训练模型 总结 摘要 本周主要通过B站刘二大人的…

酒店新科技,飞睿智能毫米波雷达人体存在感应器,智能照明创新节能新风尚

在这个日新月异的时代&#xff0c;科技正以未有的速度改变着我们的生活。从智能手机到智能家居&#xff0c;每一个细微之处都渗透着科技的魅力。而今&#xff0c;这股科技浪潮已经席卷到了酒店行业&#xff0c;为传统的住宿体验带来了翻天覆地的变化。其中&#xff0c;引人注目…