【Django REST framework电商项目笔记】第03章 数据库model设计(上)

项目初始化

数据库的设计和数据表结构

新建虚拟环境

mkvirtualenv  vueshop

在这个虚拟环境安装DjangoDjango framework

workon vueshop
pip install djangorestframwork
pip install django
pip install markdown

注意django目前最新是2.1版本, 我们用的是2.0版本, 可以指定安装2.0或者2.1降级到2.0
Pycharm的pip包管理工具基本满足项目需求
File --> Settings --> Project --> Project Interpreter
在这里插入图片描述
新建 Django 项目可以直接使用原有的虚拟环境, 最好一个项目有一个独立的虚拟环境, 互不干扰
注意: 虚拟环境必须有django的环境
新建django项目
新建APP: users

startapp users

setttings中注册 users
点击run, 查看是否启动成功

MySQL数据库配置

settings里面把默认数据库换为 MySQL:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myshop',
        'HOST': 'localhost',
        'PORT':  3306,
        'USER': 'root',
        'PASSWORD': '123456',
        'OPTIONS': {'init_command': 'SET default_storage_engine=INNODB;'}
    }
}

MySQL的数据库引擎有 InnoDB 和 MyISAM

第三方登录的库要求使用 Innodb, 否则会 migration 出错
MyISAM是MySQL的默认存储引擎。MyISAM不支持事务、也不支持外键,但其访问速度快,对事务完整性没有要求。
InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是比起MyISAM存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间以保留数据和索引

MySQL存储引擎的查看修改参考

如何查看MySQL的当前存储引擎?

进入 MySQL, 新建数据库 myshop:

mysql> create database myshop default charset=utf8;

安装 MySQL 驱动支持包:

pip install pymysql

在项目名目录下的 __init__.py中加入:
import pymysql
pymysql.install_as_MySQLdb()

安装图片处理包

pip install pillow

解决pip install pillow无法正常安装的问题

可能是之前安装 pillow 包时出错, 所以需要更新 pip, 再重新安装
python -m pip install --upgrade pip
pip install pillow

结果如下:
(blogsys) hyh@hyh-iMac:~/git/vue_shop$ pip install pillow
Collecting pillow
Using cached
https://files.pythonhosted.org/packages/3d/9e/b8a10bec874d2f6f2668b0d71ddf0d0a69ed9307d2ef111607adf81fdc1c/Pillow-5.2.0-cp35-cp35m-manylinux1_x86_64.whl
Installing collected packages: pillow
Successfully installed pillow-5.2.0

整理项目结构

  • apps 包保存所有的项目本身的应用, 将 users 移入
  • extra_apps 包保存本地安装的源码,方便修改源码适应项目需求
  • 这两个 apps 目录需要右键 Mark Driectory as --> Sources Root,,标记为源目录

新建文件夹

  • media 存放上传的图片
  • db_tools 数据库的初始化,导入原始数据

在 settings 中配置一下 app的路径

import os
import sys

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, BASE_DIR)
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))

清楚项目的目录结构:

项目目录

models设计

app 设计的思想,归类。
用户管理
商品管理
交易管理
用户的操作凌驾于app之上,可以避免循环引入。用户的收藏,用户的操作。
还可以自定义工具类,如阿里云的接口, 云片网接口
一般根据经验划分。
可以分为以下 app:

users
goods
trade
user_operation
utils

goods model设计

大类 小类 更小类
三个类之间有其从属关系。
Goods 商品类别

注意:以下代码中一些暂时没有接触到的参数在以后会介绍
help_text: 是生成接口测试文档时会用到的。
related_name: 在后面进行查询的时候会用到

这里有三个相关的类,是否意味我们要建三个model。model之间有从属的外键关系。
但是我们如果要去做一个无限分类,即可扩展。
分级别。目录树等都可以应用这个。

trade model设计

购物车 & 订单概念
对于一个商品买多个,不会在购物车里显示多个,只会增加数量
点击去结算,变成订单了
前后端分离的项目,参数名要保持一致
订单的基本信息存储在表 orderInfo
订单的订购商品存储在表 ordergoods
一对多的关系。一个订单会有多个商品。

user_operation model设计

典型操作,用户对于商品进行收藏。
用户收货地址添加
用户留言

user model 设计

用户个人信息
短信验证码

附录:goods models.py源码

from django.db import models
from datetime import datetime
from DjangoUeditor.models import UEditorField


class GoodsCategory(models.Model):
    """
    商品多级分类
    """
    CATEGORY_TYPE = (
        (1, "一级目录"),
        (2, "二级目录"),
        (3, "三级目录"),
    )

    # help_text: 是生成接口测试文档时会用到的
    # related_name: 在后面进行查询的时候会用到
    name = models.CharField(default="", max_length=30, verbose_name="类别名", help_text="类别名")
    code = models.CharField(default="", max_length=30, verbose_name="类别code", help_text="类别code")
    desc = models.TextField(default="", verbose_name="类别描述", help_text="类别描述")

    # 设置目录树的级别
    category_type = models.IntegerField(choices=CATEGORY_TYPE, verbose_name="类目级别", help_text="类目级别")
    parent_category = models.ForeignKey("self", null=True, blank=True, verbose_name="父类目级别",
                                        help_text="父目录", related_name="sub_cat", on_delete=models.CASCADE)
    is_tab = models.BooleanField(default=False, verbose_name="是否导航", help_text="是否导航")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "商品类别"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class GoodsCategoryBrand(models.Model):
    """
    商标品牌
    """
    category = models.ForeignKey(GoodsCategory, related_name="brands", null=True,
                                 verbose_name="商品类目", on_delete=models.CASCADE)
    name = models.CharField(default="", max_length=30, verbose_name="品牌名", help_text="品牌名")
    desc = models.TextField(default="", max_length=200, verbose_name="品牌描述", help_text="品牌描述")
    image = models.ImageField(max_length=200, upload_to="brands/")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "宣传品牌"
        verbose_name_plural = verbose_name
        db_table = "goods_goodsbrand"

    def __str__(self):
        return self.name


class Goods(models.Model):
    """
    商品
    """
    category = models.ForeignKey(GoodsCategory, verbose_name="商品类目", on_delete=models.CASCADE)
    goods_sn = models.CharField(default="", max_length=50, verbose_name="商品唯一货号")
    name = models.CharField(max_length=100, verbose_name="商品名")
    click_num = models.IntegerField(default=0, verbose_name="点击数")
    sold_num = models.IntegerField(default=0, verbose_name="商品销售量")
    fav_num = models.IntegerField(default=0, verbose_name="收藏量")
    goods_num = models.IntegerField(default=0, verbose_name="库存量")
    market_price = models.FloatField(default=0, verbose_name="市场价格")
    shop_price = models.FloatField(default=0, verbose_name="本店价格")
    goods_brief = models.TextField(max_length=500, verbose_name="商品简短描述")
    goods_desc = UEditorField(verbose_name=u"内容", imagePath="goods/images/", width=1000,
                              height=300, filePath="goods/files/", default="")
    ship_free = models.BooleanField(default=True, verbose_name="是否承担运费")
    goods_front_image = models.ImageField(upload_to="goods/images/", null=True, verbose_name="封面图")
    is_new = models.BooleanField(default=False, verbose_name="是否新品")
    is_hot = models.BooleanField(default=False, verbose_name="是否热销")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "商品"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.name


class IndexAd(models.Model):
    """
    首页商品类别广告
    """
    category = models.ForeignKey(GoodsCategory, related_name="category", verbose_name="商品类目",
                                 on_delete=models.CASCADE)                          # null=True
    goods = models.ForeignKey(Goods, related_name="goods", on_delete=models.CASCADE)

    class Meta:
        verbose_name = "首页商品类别广告"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods.name


class GoodsImage(models.Model):
    """
    商品详情页轮播图
    """
    goods = models.ForeignKey(Goods, verbose_name="商品", related_name="images", on_delete=models.CASCADE)
    image = models.ImageField(upload_to="", verbose_name="图片", null=True, blank=True)
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "商品轮播图"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods.name


class Banner(models.Model):
    """
    首页轮播的商品图, 为适配首页大图
    """
    goods = models.ForeignKey(Goods, verbose_name="商品", on_delete=models.CASCADE)
    image = models.ImageField(upload_to="banner/", verbose_name="轮播图片")
    index = models.IntegerField(default=0, verbose_name="轮播顺序")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "首页轮播商品"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.goods.name


class HotSearchWords(models.Model):
    """
    热搜词
    """
    keywords = models.CharField(default="", max_length=20, verbose_name="热搜词")
    index = models.IntegerField(default=0, verbose_name="排序")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "热搜词"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.keywords

附录:trade models.py源码

from django.db import models
from django.contrib.auth import get_user_model
from goods.models import Goods
from datetime import datetime

User = get_user_model()

class ShoppingCart(models.Model):
    """
    购物车
    """
    user = models.ForeignKey(User, verbose_name=u"用户", on_delete=models.CASCADE)
    goods = models.ForeignKey(Goods, verbose_name=u"商品", on_delete=models.CASCADE)
    nums = models.IntegerField(default=0, verbose_name="购物数量")

    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")

    class Meta:
        verbose_name = "购物车"
        verbose_name_plural = verbose_name

    def __str__(self):
        return "%s(%d)".format(self.goods.name, self.nums)


class OrderInfo(models.Model):
    """
    订单信息
    """
    ORDER_STATUS = (
        ("TRADE_SUCCESS", "成功"),
        ("TRADE_CLOSED", "超时关闭"),
        ("WAIT_BUYER_PAY", "交易创建"),
        ("TRADE_FINISHED", "交易结束"),
        ("paying", "待支付"),
    )
    # PAY_TYPE = (
    #     ("alipay", "支付宝"),
    #     ("wechat", "微信")
    # )

    user = models.ForeignKey(User, verbose_name="用户", null=True, on_delete=models.CASCADE)
    order_sn = models.CharField(max_length=30, null=True, blank=True, unique=True, verbose_name="订单号")
    trade_no = models.CharField(max_length=100, null=True, blank=True, unique=True, verbose_name=u"交易号")
    pay_status = models.CharField(choices=ORDER_STATUS, default="paying", max_length=30, verbose_name="订单状态")
    post_script = models.CharField(max_length=200, verbose_name="订单留言")
    order_mount = models.FloatField(default=0.0, verbose_name="订单金额")
    pay_time = models.DateTimeField(null=True, blank=True, verbose_name="支付时间")

    # 用户信息
    address = models.CharField(max_length=100, default="", verbose_name="收货地址")
    signer_name = models.CharField(max_length=20, default="", verbose_name="签收人")
    signer_mobile = models.CharField(max_length=11, verbose_name="联系电话")

    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = u"订单"
        verbose_name_plural = verbose_name

    def __str__(self):
        return str(self.order_sn)


class OrderGoods(models.Model):
    """
    订单的商品详情
    """
    order = models.ForeignKey(OrderInfo, verbose_name="订单信息", related_name="goods", on_delete=models.CASCADE)
    goods = models.ForeignKey(Goods, verbose_name="商品", on_delete=models.CASCADE)
    goods_num = models.IntegerField(default=0, verbose_name="商品数量")

    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "订单商品"
        verbose_name_plural = verbose_name

    def __str__(self):
        return str(self.order.order_sn)

附录:user_operation models.py源码

from django.db import models
from django.contrib.auth import get_user_model
from goods.models import Goods
from datetime import datetime

User = get_user_model()


class UserFav(models.Model):
    """
    用户收藏
    """
    user = models.ForeignKey(User, verbose_name="用户", on_delete=models.CASCADE)
    goods = models.ForeignKey(Goods, verbose_name="商品", help_text="商品id", on_delete=models.CASCADE)
    add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")

    class Meta:
        verbose_name = "用户收藏"
        verbose_name_plural = verbose_name
        # 多个字段作为一个联合唯一索引
        unique_together = ("user", "goods")

    def __str__(self):
        #return self.user.user
        return self.user.username


class UserLeavingMessage(models.Model):
    """
    用户留言
    """
    MESSAGE_CHOICES = (
        (1, "留言"),
        (2, "投诉"),
        (3, "询问"),
        (4, "售后"),
        (5, "求购")
    )

    user = models.ForeignKey(User, verbose_name="用户", on_delete=models.CASCADE)
    message_type = models.IntegerField(default=1, choices=MESSAGE_CHOICES, verbose_name="留言类型",
                                       help_text=u"留言类型: 1(留言);2(投诉);3(询问);4(售后);5(求购)")
    subject = models.CharField(max_length=100, default="", verbose_name="主题")
    message = models.TextField(default="", verbose_name="留言内容", help_text="留言内容")
    file = models.FileField(upload_to="message/images/", verbose_name="上传的文件", help_text="上传的文件")

    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "用户留言"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.subject


class UserAddress(models.Model):
    """
    用户收货地址
    """
    user = models.ForeignKey(User, verbose_name="用户", on_delete=models.CASCADE)
    province = models.CharField(max_length=100, default="", verbose_name="省份")
    city = models.CharField(max_length=100, default="", verbose_name="城市")
    district = models.CharField(max_length=100, default="", verbose_name="区域")
    address = models.CharField(max_length=100, default="", verbose_name="详细地址")
    signer_name = models.CharField(max_length=100, default="", verbose_name="签收人")
    signer_mobile = models.CharField(max_length=11, default="", verbose_name="电话")

    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "收货地址"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.address

附录:user models.py源码

from django.db import models
from django.contrib.auth.models import AbstractUser
from datetime import datetime


class UserProfile(AbstractUser):
    """
    用户表
    """
    GENDER_CHOICES = (
        ("male", u"男"),
        ("female", u"女")
    )

    name = models.CharField(max_length=30, null=True, blank=True, verbose_name="姓名")
    birthday = models.DateField(null=True, blank=True, verbose_name="出生年月")
    gender = models.CharField(max_length=6, choices=GENDER_CHOICES, default="female", verbose_name="性别")
    mobile = models.CharField(null=True, blank=True, max_length=11, verbose_name="电话")
    email = models.EmailField(max_length=100, null=True, blank=True, verbose_name="邮箱")

    class Meta:
        verbose_name = "用户"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username


class VerifyCode(models.Model):
    """
    短信验证码
    """
    code = models.CharField(max_length=10, verbose_name="验证码")
    mobile = models.CharField(max_length=11, verbose_name="电话")
    add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")

    class Meta:
        verbose_name = "短信验证码"
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.code

猜你喜欢

转载自blog.csdn.net/Yuyh131/article/details/82897641