当前位置: 首页 > news >正文

【Django开发】django美多商城项目完整开发4.0第12篇:商品部分,表结构【附代码文档】

本教程的知识点为: 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后端接口设计: 用户部分 JWT 什么是JWT 起源 传统的session认证 用户部分 登录 1. 业务说明 2. 后端接口设计 3. 后端实现 登录 使用登录的流程 创建模型类 urllib使用说明 登录回调处理 登录 使用登录的流程 创建模型类 urllib使用说明 绑定用户身份接口 邮件与验证 学习目标: 业务说明: 技术说明: 保存邮箱并发送验证邮件 省市区地址查询 数据库建表 说明 页面静态化 注意 定时任务 安装 部分 详情页 异步任务的触发 。 后端接口设计 收货地址 使用缓存 安装 使用方法 为省市区视图添加缓存 数据库表设计 表结构 数据表结构 首页数据表结构 Docker使用 Docker简介 用户浏览历史记录 1. 保存 后端接口设计 后端实现 搜索 1. 需求分析 2. 搜索引擎原理 3. Elasticsearch 部分 业务需求分析 技术实现 数据存储设计 1. Redis保存已登录用户 商品部分 业务需求分析 技术实现 查询数据 1. 后端接口设计 部分 业务需求分析 技术实现 登录合并 修改登录视图 部分 保存 1. 后端接口设计 2. 后端实现 保存的思路 创建数据库模型类 接入 开发平台登录 沙箱环境 Xadmin 1. 安装 2. 使用 站点的全局配置 站点Model管理。 在Ubuntu中安装 2. 启动与停止 3. 镜像操作 端与自定义文件存储系统 1. 的Python客户端 安装 使用。

完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/Django/django美多商城项目完整开发4.0/note.md

感兴趣的小伙伴可以自取哦~


全套教程部分目录:


部分文件图片:

商品部分

数据库表设计

在电商中对于商品,有两个重要的概念:SPUSKU

  • SPU = Standard Product Unit (标准产品单位)

SPU是商品信息聚合的最小单位,是一组可服用、易检索的标准化信息的集合,该集合描述了一个产品的特性。

通俗的讲,属性值、特性相同的商品就可以称为一个SPU。

例如:

iPhone X 就是一个SPU,与商家、颜色、款式、规格、套餐等都无关。

  • SKU = Stock Keeping Unit (库存量单位)

SKU即库存进出计量的单位,可以是以件、盒、托盘等为单位,是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。在服装、鞋类商品中使用最多最普遍。

例如:

iPhone X 全网通黑色256G 就是一个SKU,表示了具体的规格、颜色等信息。

表结构

商品数据表结构

商品数据库表结构

首页广告数据表结构

首页广告数据表结构

数据库模型类

创建商品应用goods,商品数据模型类

class GoodsCategory(BaseModel):"""商品类别"""name = models.CharField(max_length=10, verbose_name='名称')parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父类别')class Meta:db_table = 'tb_goods_category'verbose_name = '商品类别'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass GoodsChannel(BaseModel):"""商品频道"""group_id = models.IntegerField(verbose_name='组号')category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='顶级商品类别')url = models.CharField(max_length=50, verbose_name='频道页面链接')sequence = models.IntegerField(verbose_name='组内顺序')class Meta:db_table = 'tb_goods_channel'verbose_name = '商品频道'verbose_name_plural = verbose_namedef __str__(self):return self.category.nameclass Brand(BaseModel):"""品牌"""name = models.CharField(max_length=20, verbose_name='名称')logo = models.ImageField(verbose_name='Logo图片')first_letter = models.CharField(max_length=1, verbose_name='品牌首字母')class Meta:db_table = 'tb_brand'verbose_name = '品牌'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass Goods(BaseModel):"""商品SPU"""name = models.CharField(max_length=50, verbose_name='名称')brand = models.ForeignKey(Brand, on_delete=models.PROTECT, verbose_name='品牌')category1 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat1_goods', verbose_name='一级类别')category2 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat2_goods', verbose_name='二级类别')category3 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat3_goods', verbose_name='三级类别')sales = models.IntegerField(default=0, verbose_name='销量')comments = models.IntegerField(default=0, verbose_name='评价数')class Meta:db_table = 'tb_goods'verbose_name = '商品'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass GoodsSpecification(BaseModel):"""商品规格"""goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')name = models.CharField(max_length=20, verbose_name='规格名称')class Meta:db_table = 'tb_goods_specification'verbose_name = '商品规格'verbose_name_plural = verbose_namedef __str__(self):return '%s: %s' % (self.goods.name, self.name)class SpecificationOption(BaseModel):"""规格选项"""spec = models.ForeignKey(GoodsSpecification, on_delete=models.CASCADE, verbose_name='规格')value = models.CharField(max_length=20, verbose_name='选项值')class Meta:db_table = 'tb_specification_option'verbose_name = '规格选项'verbose_name_plural = verbose_namedef __str__(self):return '%s - %s' % (self.spec, self.value)class SKU(BaseModel):"""商品SKU"""name = models.CharField(max_length=50, verbose_name='名称')caption = models.CharField(max_length=100, verbose_name='副标题')goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')category = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, verbose_name='从属类别')price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='单价')cost_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='进价')market_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='市场价')stock = models.IntegerField(default=0, verbose_name='库存')sales = models.IntegerField(default=0, verbose_name='销量')comments = models.IntegerField(default=0, verbose_name='评价数')is_launched = models.BooleanField(default=True, verbose_name='是否上架销售')default_image_url = models.CharField(max_length=200, default='', null=True, blank=True, verbose_name='默认图片')class Meta:db_table = 'tb_sku'verbose_name = '商品SKU'verbose_name_plural = verbose_namedef __str__(self):return '%s: %s' % (self.id, self.name)class SKUImage(BaseModel):"""SKU图片"""sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')image = models.ImageField(verbose_name='图片')class Meta:db_table = 'tb_sku_image'verbose_name = 'SKU图片'verbose_name_plural = verbose_namedef __str__(self):return '%s %s' % (self.sku.name, self.id)class SKUSpecification(BaseModel):"""SKU具体规格"""sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')spec = models.ForeignKey(GoodsSpecification, on_delete=models.PROTECT, verbose_name='规格名称')option = models.ForeignKey(SpecificationOption, on_delete=models.PROTECT, verbose_name='规格值')class Meta:db_table = 'tb_sku_specification'verbose_name = 'SKU规格'verbose_name_plural = verbose_namedef __str__(self):return '%s: %s - %s' % (self.sku, self.spec.name, self.option.value)

创建广告内容应用contents,广告数据模型类

class ContentCategory(BaseModel):"""广告内容类别"""name = models.CharField(max_length=50, verbose_name='名称')key = models.CharField(max_length=50, verbose_name='类别键名')class Meta:db_table = 'tb_content_category'verbose_name = '广告内容类别'verbose_name_plural = verbose_namedef __str__(self):return self.nameclass Content(BaseModel):"""广告内容"""category = models.ForeignKey(ContentCategory, on_delete=models.PROTECT, verbose_name='类别')title = models.CharField(max_length=100, verbose_name='标题')url = models.CharField(max_length=300, verbose_name='内容链接')image = models.ImageField(null=True, blank=True, verbose_name='图片')text = models.TextField(null=True, blank=True, verbose_name='内容')sequence = models.IntegerField(verbose_name='排序')status = models.BooleanField(default=True, verbose_name='是否展示')class Meta:db_table = 'tb_content'verbose_name = '广告内容'verbose_name_plural = verbose_namedef __str__(self):return self.category.name + ': ' + self.title

FastDFS分布式文件系统

1. 什么是FastDFS

FastDFS 是用 c 语言编写的一款开源的分布式文件系统。FastDFS 为互联网量身定制, 充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用 FastDFS 很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

FastDFS 架构包括 Tracker serverStorage server。客户端请求 Tracker server 进行文 件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。

  • Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些 策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器调度服务器

  • Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上, Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将 storage 称为存储服务器

FastDFS结构

服务端两个角色:

  • Tracker: 管理集群,tracker 也可以实现集群。每个 tracker 节点地位平等。收集 Storage 集群的状态。
  • Storage: 实际保存文件, Storage 分为多个组,每个组之间保存的文件是不同的。每 个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有 主从的概念。

2. 文件上传流程

上传文件流程

客户端上传文件后存储服务器将文件 ID 返回给客户端,此文件 ID 用于以后访问该文 件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

文件名

  • 组名:文件上传后所在的 storage 组名称,在文件上传成功后有 storage 服务器返回, 需要客户端自行保存。
  • 虚拟磁盘路径:storage 配置的虚拟路径,与磁盘选项 store_path*对应。如果配置了 store_path0 则是 M00,如果配置了 store_path1 则是 M01,以此类推。
  • 数据两级目录:storage 服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据 文件。
  • 文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储 服务器 IP 地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

3. 简易FastDFS构建

简易FastDFS

Docker使用

我们使用Docker来安装FastDFS。

学习目标:

  • 了解 Docker 与虚拟机的不同点,相比的优势
  • 掌握 Docker 的启动方法
  • 掌握 Docker 镜像操作
  • 掌握 Docker 容器操作

相关文章:

【Django开发】django美多商城项目完整开发4.0第12篇:商品部分,表结构【附代码文档】

本教程的知识点为: 项目准备 项目准备 配置 1. 修改settings/dev.py 文件中的路径信息 2. INSTALLED_APPS 3. 数据库 用户部分 图片 1. 后端接口设计: 视图原型 2. 具体视图实现 用户部分 使用Celery完成发送 判断帐号是否存在 1. 判断用户名是否存在 后…...

IDEA2023版中TODO的使用

介绍:TODO其实本质上还是注释,只不过加上了TODO这几个字符,可以让使用者快速找到。 注意:在类、接口等文件中,注释是使用// 即:// TODO 注释内容 在配置文件中,注释是使用# 即:# TO…...

windows 搭建flutter环境,开发windows程序

环境安装配置: 下载flutter sdk https://docs.flutter.dev/get-started/install/windows 下载到本地后,随便找个地方解压,然后配置下系统环境变量 编译windows程序本地需要安装vs2019或更新的开发环境 主要就这2步安装后就可以了&#xff0…...

支持向量机算法(三):非线性支持向量原理层层拆解,精读公式每一处细节

支持向量机算法(一):像讲故事一样讲明白它的原理及实现奥秘-CSDN博客 支持向量机算法(二):层层拆解,精读公式每一处细节-CSDN博客 支持向量机算法(一)、算法&#xff0…...

一文读懂iOS中的Crash捕获、分析以及防治

Crash系统性总结 Crash捕获与分析Crash收集符号化分析 Crash类别以及解法分析子线程访问UI而导致的崩溃unrecognized selector send to instance xxxKVO crashKVC造成的crashNSTimer导致的Crash野指针Watch Dog超时造成的crash其他crash待补充 参考文章: 对于iOS端开…...

代码随想录刷题day11|(链表篇)206.翻转链表

目录 一、链表理论基础 二、翻转链表思路 双指针解法 递归解法 三、相关算法题目 四、总结 一、链表理论基础 代码随想录 (programmercarl.com) 二、翻转链表思路 两种方法:双指针解法和递归解法 双指针解法 首先定义一个指针curr,初始化为原…...

【STM32-学习笔记-8-】I2C通信

文章目录 I2C通信Ⅰ、硬件电路Ⅱ、IIC时序基本单元① 起始条件② 终止条件③ 发送一个字节④ 接收一个字节⑤ 发送应答⑥ 接收应答 Ⅲ、IIC时序① 指定地址写② 当前地址读③ 指定地址读 Ⅳ、MPU6050---6轴姿态传感器(软件I2C)1、模块内部电路2、寄存器地…...

2025年1月17日(点亮三色LED)

系统信息: Raspberry Pi Zero 2W 系统版本: 2024-10-22-raspios-bullseye-armhf Python 版本:Python 3.9.2 已安装 pip3 支持拍摄 1080p 30 (1092*1080), 720p 60 (1280*720), 60/90 (640*480) 已安装 vim 已安装 git 学习目标:…...

ASP .NET Core 学习 (.NET 9)- 创建 API项目,并配置Swagger及API 分组或版本

本系列为个人学习 ASP .NET Core学习全过程记录,基于.NET 9 和 VS2022 ,实现前后端分离项目基础框架搭建和部署,以简单、易理解为主,注重页面美观度和后台代码简洁明了,可能不会使用过多的高级语法和扩展,后…...

mysql-5.7.18保姆级详细安装教程

本文主要讲解如何安装mysql-5.7.18数据库: 将绿色版安装包mysql-5.7.18-winx64解压后目录中内容如下图,该例是安装在D盘根目录。 在mysql安装目录中新建my.ini文件,文件内容及各配置项内容如下图,需要先将配置项【skip-grant-tab…...

RK3588平台开发系列讲解(NPU篇)NPU 驱动的组成

文章目录 一、NPU 驱动组成二、查询 NPU 驱动版本三、查询 rknn_server 版本四、查询 librknn_runtime 版本沉淀、分享、成长,让自己和他人都能有所收获!😄 一、NPU 驱动组成 NPU 驱动版本、rknn_server 版本、librknn_runtime 版本以及 RKNN Toolkit 版本的对应关系尤为重…...

ESP32学习笔记_FreeRTOS(6)——Event and Notification

摘要(From AI): 这篇博客详细介绍了 FreeRTOS 中的事件组和任务通知机制,讲解了事件组如何通过位操作实现任务间的同步与通信,以及任务如何通过通知机制进行阻塞解除和数据传递。博客提供了多个代码示例,展示了如何使用事件组和任务通知在多任…...

力扣-数组-350 两个数组的交集Ⅱ

解析 与刚刚的《两个数组的交集》一样&#xff0c;只是这道题允许重复&#xff0c;将上一题的set去除即可。 代码 class Solution { public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {vector<int> res;int index1 …...

云原生第二次练习

1.判断192.168.1.0/24网络中&#xff0c;当前在线的ip有哪些&#xff0c;并编写脚本打印出来。 #!/bin/bash for ip in $(seq 1 254); doping -c 1 -W 1 "192.168.1.$ip" > /dev/null 2>&1if [ $? -eq 0 ]; thenecho "192.168.1.$ip is online&qu…...

SpringMVC复习笔记

文章目录 SpringMVC 概念和基本使用SpringMVC 简介SpringMVC 核心组件和调用流程SpringMVC 基本使用第一步&#xff1a;导入依赖第二步&#xff1a;Controller 层开发第三步&#xff1a;SpringMVC 配置类配置核心组件第四步&#xff1a;SpringMVC 环境搭建第五步&#xff1a;部…...

前端小案例——网页井字棋

前言&#xff1a;我们在学习完了HTML、CSS和JavaScript之后&#xff0c;就会想着使用这三个东西去做一些小案例&#xff0c;不过又没有什么好的案例让我们去练手&#xff0c;本篇文章就提供里一个案例——网页井字棋。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可…...

ComfyUI-PromptOptimizer:文生图提示优化节点

ComfyUI-PromptOptimizer 是 ComfyUI 的一个自定义节点&#xff0c;旨在优化文本转图像模型的提示。它将用户输入的提示转换为更详细、更多样化、更生动的描述&#xff0c;使其更适合生成高质量的图像。无需本地模型。 1、功能 提示优化&#xff1a;优化用户输入的提示以生成…...

AudioGPT全新的 音频内容理解与生成系统

AudioGPT全新的 音频内容理解与生成系统 ChatGPT、GPT-4等大型语言模型 (LLM) 在语言理解、生成、交互和推理方面表现出的非凡能力,引起了学界和业界的极大关注,也让人们看到了LLM在构建通用人工智能 (AGI) 系统方面的潜力。 现有的GPT模型具有极高的语言生成能力,是目前最…...

thinkphp6 + redis实现大数据导出excel超时或内存溢出问题解决方案

redis下载安装&#xff08;window版本&#xff09; 参考地址&#xff1a;https://blog.csdn.net/Ci1693840306/article/details/144214215 php安装redis扩展 参考链接&#xff1a;https://blog.csdn.net/jianchenn/article/details/106144313 解决思路&#xff1a;&#xff0…...

Hexo + NexT + Github搭建个人博客

文章目录 一、 安装二、配置相关项NexT config更新主题主题样式本地实时预览常用命令 三、主题设置1.侧边栏2.页脚3.帖子发布字数统计 4.自定义自定义页面Hexo 的默认页面自定义 404 页自定义样式 5.杂项搜索服务 四、第三方插件NexT 自带插件评论系统阅读和访问人数统计 五、部…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣&#xff08;LeetCode&#xff09; ​遍历字符串​&#xff1a;通过外层循环逐一检查每个字符。​遇到 ? 时处理​&#xff1a; 内层循环遍历小写字母&#xff08;a 到 z&#xff09;。对每个字母检查是否满足&#xff1a; ​与…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...