数据库表设计

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

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

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

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

    例如:

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

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

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

    例如:

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

总结:

SPU是某一类商品

SKU是某一件商品

商品数据表结构

首页广告数据表结构

数据库模型类

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

  1. python ../../manage.py startapp goods
  1. class GoodsCategory(BaseModel):
  2. """
  3. 商品类别
  4. """
  5. name = models.CharField(max_length=10, verbose_name='名称')
  6. parent = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父类别')
  7.  
  8. class Meta:
  9. db_table = 'tb_goods_category'
  10. verbose_name = '商品类别'
  11. verbose_name_plural = verbose_name
  12.  
  13. def __str__(self):
  14. return self.name
  15.  
  16. class GoodsChannel(BaseModel):
  17. """
  18. 商品频道
  19. """
  20. group_id = models.IntegerField(verbose_name='组号')
  21. category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='顶级商品类别')
  22. url = models.CharField(max_length=50, verbose_name='频道页面链接')
  23. sequence = models.IntegerField(verbose_name='组内顺序')
  24.  
  25. class Meta:
  26. db_table = 'tb_goods_channel'
  27. verbose_name = '商品频道'
  28. verbose_name_plural = verbose_name
  29.  
  30. def __str__(self):
  31. return self.category.name
  32.  
  33. class Brand(BaseModel):
  34. """
  35. 品牌
  36. """
  37. name = models.CharField(max_length=20, verbose_name='名称')
  38. logo = models.ImageField(verbose_name='Logo图片')
  39. first_letter = models.CharField(max_length=1, verbose_name='品牌首字母')
  40.  
  41. class Meta:
  42. db_table = 'tb_brand'
  43. verbose_name = '品牌'
  44. verbose_name_plural = verbose_name
  45.  
  46. def __str__(self):
  47. return self.name
  48.  
  49. class Goods(BaseModel):
  50. """
  51. 商品SPU
  52. """
  53. name = models.CharField(max_length=50, verbose_name='名称')
  54. brand = models.ForeignKey(Brand, on_delete=models.PROTECT, verbose_name='品牌')
  55. category1 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat1_goods', verbose_name='一级类别')
  56. category2 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat2_goods', verbose_name='二级类别')
  57. category3 = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, related_name='cat3_goods', verbose_name='三级类别')
  58. sales = models.IntegerField(default=0, verbose_name='销量')
  59. comments = models.IntegerField(default=0, verbose_name='评价数')
  60.  
  61. class Meta:
  62. db_table = 'tb_goods'
  63. verbose_name = '商品'
  64. verbose_name_plural = verbose_name
  65.  
  66. def __str__(self):
  67. return self.name
  68.  
  69. class GoodsSpecification(BaseModel):
  70. """
  71. 商品规格
  72. """
  73. goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
  74. name = models.CharField(max_length=20, verbose_name='规格名称')
  75.  
  76. class Meta:
  77. db_table = 'tb_goods_specification'
  78. verbose_name = '商品规格'
  79. verbose_name_plural = verbose_name
  80.  
  81. def __str__(self):
  82. return '%s: %s' % (self.goods.name, self.name)
  83.  
  84. class SpecificationOption(BaseModel):
  85. """
  86. 规格选项
  87. """
  88. spec = models.ForeignKey(GoodsSpecification, on_delete=models.CASCADE, verbose_name='规格')
  89. value = models.CharField(max_length=20, verbose_name='选项值')
  90.  
  91. class Meta:
  92. db_table = 'tb_specification_option'
  93. verbose_name = '规格选项'
  94. verbose_name_plural = verbose_name
  95.  
  96. def __str__(self):
  97. return '%s - %s' % (self.spec, self.value)
  98.  
  99. class SKU(BaseModel):
  100. """
  101. 商品SKU
  102. """
  103. name = models.CharField(max_length=50, verbose_name='名称')
  104. caption = models.CharField(max_length=100, verbose_name='副标题')
  105. goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
  106. category = models.ForeignKey(GoodsCategory, on_delete=models.PROTECT, verbose_name='从属类别')
  107. price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='单价')
  108. cost_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='进价')
  109. market_price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='市场价')
  110. stock = models.IntegerField(default=0, verbose_name='库存')
  111. sales = models.IntegerField(default=0, verbose_name='销量')
  112. comments = models.IntegerField(default=0, verbose_name='评价数')
  113. is_launched = models.BooleanField(default=True, verbose_name='是否上架销售')
  114. default_image_url = models.CharField(max_length=200, default='', null=True, blank=True, verbose_name='默认图片')
  115.  
  116. class Meta:
  117. db_table = 'tb_sku'
  118. verbose_name = '商品SKU'
  119. verbose_name_plural = verbose_name
  120.  
  121. def __str__(self):
  122. return '%s: %s' % (self.id, self.name)
  123.  
  124. class SKUImage(BaseModel):
  125. """
  126. SKU图片
  127. """
  128. sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')
  129. image = models.ImageField(verbose_name='图片')
  130.  
  131. class Meta:
  132. db_table = 'tb_sku_image'
  133. verbose_name = 'SKU图片'
  134. verbose_name_plural = verbose_name
  135.  
  136. def __str__(self):
  137. return '%s %s' % (self.sku.name, self.id)
  138.  
  139. class SKUSpecification(BaseModel):
  140. """
  141. SKU具体规格
  142. """
  143. sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name='sku')
  144. spec = models.ForeignKey(GoodsSpecification, on_delete=models.PROTECT, verbose_name='规格名称')
  145. option = models.ForeignKey(SpecificationOption, on_delete=models.PROTECT, verbose_name='规格值')
  146.  
  147. class Meta:
  148. db_table = 'tb_sku_specification'
  149. verbose_name = 'SKU规格'
  150. verbose_name_plural = verbose_name
  151.  
  152. def __str__(self):
  153. return '%s: %s - %s' % (self.sku, self.spec.name, self.option.value)

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

  1. python ../../manage.py startapp contents
  1. class ContentCategory(BaseModel):
  2. """
  3. 广告内容类别
  4. """
  5. name = models.CharField(max_length=50, verbose_name='名称')
  6. key = models.CharField(max_length=50, verbose_name='类别键名')
  7.  
  8. class Meta:
  9. db_table = 'tb_content_category'
  10. verbose_name = '广告内容类别'
  11. verbose_name_plural = verbose_name
  12.  
  13. def __str__(self):
  14. return self.name
  15.  
  16. class Content(BaseModel):
  17. """
  18. 广告内容
  19. """
  20. category = models.ForeignKey(ContentCategory, on_delete=models.PROTECT, verbose_name='类别')
  21. title = models.CharField(max_length=100, verbose_name='标题')
  22. url = models.CharField(max_length=300, verbose_name='内容链接')
  23. image = models.ImageField(null=True, blank=True, verbose_name='图片')
  24. text = models.TextField(null=True, blank=True, verbose_name='内容')
  25. sequence = models.IntegerField(verbose_name='排序')
  26. status = models.BooleanField(default=True, verbose_name='是否展示')
  27.  
  28. class Meta:
  29. db_table = 'tb_content'
  30. verbose_name = '广告内容'
  31. verbose_name_plural = verbose_name
  32.  
  33. def __str__(self):
  34. return self.category.name + ': ' + self.title

执行数据库迁移

  1. python manage.py makemigrations
  2. python manage.py migrate

Django商城项目笔记No.18商品部分-数据表创建的更多相关文章

  1. Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid

    Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...

  2. Django商城项目笔记No.10用户部分-登录接口

    Django商城项目笔记No.10用户部分-登录接口 添加url路由 接下来第二步,增加返回内容: 增加结果如下: 配置:上边的方法定义了返回的内容都有哪些,那这个方法jwt还不知道,需要配置: 修改 ...

  3. Django商城项目笔记No.5用户部分-注册接口-短信验证码

    Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...

  4. Django商城项目笔记No.11用户部分-QQ登录1获取QQ登录网址

    Django商城项目笔记No.11用户部分-QQ登录 QQ登录,亦即我们所说的第三方登录,是指用户可以不在本项目中输入密码,而直接通过第三方的验证,成功登录本项目. 若想实现QQ登录,需要成为QQ互联 ...

  5. Django商城项目笔记No.9用户部分-注册接口签发JWTtoken

    Django商城项目笔记No.9用户部分-注册接口签发JWTtoken 我们在验证完用户的身份后(检验用户名和密码),需要向用户签发JWT,在需要用到用户身份信息的时候,还需核验用户的JWT. 关于签 ...

  6. Django商城项目笔记No.8用户部分-注册接口实现

    Django商城项目笔记No.8用户部分-注册接口实现 users的view.py中增加如下代码 class RegisterUserView(CreateAPIView): "" ...

  7. Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在

    Django商城项目笔记No.7用户部分-注册接口-判断用户名和手机号是否存在 判断用户名是否存在 后端视图代码实现,在users/view.py里编写如下代码 class UsernameCount ...

  8. Django商城项目笔记No.6用户部分-注册接口-短信验证码实现celery异步

    Django商城项目笔记No.4用户部分-注册接口-短信验证码实现celery异步 接上一篇,如何解决前后端请求跨域问题? 首先想一下,为什么图片验证码请求的也是后端的api.meiduo.site: ...

  9. Django商城项目笔记No.4用户部分-注册接口-图片验证码

    Django商城项目笔记No.4用户部分-注册接口-图片验证码 1.首先分析注册业务接口 1.1.分析可得,至少这么几个接口 图片验证码 短信验证码 用户名是否存在 手机号是否存在 整体注册接口 图片 ...

随机推荐

  1. U3D Invoke系列函数

    public void Invoke(string methodName, float time) 多少秒后执行某个函数 参数说明: methodName:要执行的函数的名称 time:秒数,time ...

  2. string基本字符序列容器(竞赛时常用的使用方法总结)

    C语言只提供了一个char类型用来处理字符,而对于字符串,只能通过字符串数组来处理,而C++STL提供了string基本字符序列容器来处理字符串,可以将其理解为字符串类,它提供了添加,删除,替换.查找 ...

  3. 传统项目转前端工程化——路由跳转时出现浏览器锁死和白屏【该死的同步ajax】

    [一开始我想到是该死的同步ajax,但我没验证,把他忽略了] 在探索前端工程化vue-cli做spa时,从搜索结果页跳转商品详情页时,因为详情页有很多ajax请求,并且都用的同步请求,就会导致请求时浏 ...

  4. [日常] Go语言圣经--浮点数习题

    练习 3.1: 如果f函数返回的是无限制的float64值,那么SVG文件可能输出无效的多边形元素(虽然许多SVG渲染器会妥善处理这类问题).修改程序跳过无效的多边形. 练习 3.2: 试验math包 ...

  5. Docker的下载与安装

    一丶下载 1.win10之外的 Docker下载地址: https://www.docker.com/products/docker-toolbox 2.win10 Docker下载地址: https ...

  6. 步步深入MySQL:架构->查询执行流程->SQL解析顺序!

    一.前言 一直是想知道一条SQL语句是怎么被执行的,它执行的顺序是怎样的,然后查看总结各方资料,就有了下面这一篇博文了. 本文将从MySQL总体架构--->查询执行流程--->语句执行顺序 ...

  7. Java - fail-fast机制

    Java提高篇(三四)-----fail-fast机制 在JDK的Collection中我们时常会看到类似于这样的话: 例如,ArrayList: 注意,迭代器的快速失败行为无法得到保证,因为一般来说 ...

  8. Java - 线程优先级和守护线程

    Java多线程系列--“基础篇”10之 线程优先级和守护线程 概要 本章,会对守护线程和线程优先级进行介绍.涉及到的内容包括:1. 线程优先级的介绍2. 线程优先级的示例3. 守护线程的示例 转载请注 ...

  9. JS中那些让人头昏眼花的弯子

    看别人在讨论,于是整理了下,大家来看看下面代码中1-11分别输出的答案是什么???(不要试过再说) var obj={ a:1, b:2, add:function(c,d){ console.log ...

  10. linux_shell_数组

    shell数组类似与C语言,数组下标由0开始编号.想要获取数组中的元素要利用下标. 1.首先定义数组 在shell中,用括号来表示数组,数组元素用“空格”符号分割开.列: name=("d& ...