Django+Vue开发生鲜电商平台之3.数据模型设计和资源导入(上)

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 文章目录一、项目初始化二、数据模型设计1.用户数据模型设计2.商品数据模型设计3.交易数据模型设计4.用户操作数据模型设计三、xadmin后台管理系统的配置四、数据迁移和数据导入1.migration原理和表的生成2.导入商品类别和商品数据

一、项目初始化

在虚拟环境安装好之后,需要安装DjangoDjango REST framework,直接在虚拟环境下使用pip install djangopip install djangorestframework。为了支持Django REST framework,还需要安装markdown和django-filter,命令类似。

在PyCharm新建项目,需要选择Django,而不是Pure Python,建立好之后,需要选择解释器为建立的虚拟环境所对应的解释器,选择模板语言为Django,设置应用名为users,并取消勾选Enable Django admin。


项目创建后,通过点击PyCharm导航栏Run下的Run 'Project Name'或者命令行执行python manage.py runserver即可运行项目,再访问http://127.0.0.1:8000/如果看到以下页面即说明项目初始化成功:


创建项目后,主应用目录下会有一个settings.py文件,是关于项目的配置,其中有关于数据库的配置,如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

显然,指明了数据库为sqlite,这也是Django的默认数据库,需要修改为MySQL,如下:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'fresh_ec',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST':'127.0.0.1',
        'OPTIONS': {'init_command': 'SET default_storage_engine=INNODB;'}
    }
}

因为后面第三方登录时进行数据迁移的需要,需要添加OPTIONS参数,设置存储引擎为INNODB,否则会报错。

此时再运行项目就会报错:

django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?

提示安装MySQL驱动,直接通过pip install mysqlclient安装即可。


在安装过程中可能会报错ERROR: Command errored out with exit status 1,需要在https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient中下载对应系统和Python版本的安装文件并将其拷贝到虚拟环境目录下通过pip install 文件名.whl进行安装。


另外,因为项目中需要进行图片处理,因此需要安装图片处理库pillow,通过pip install pillow安装即可。


还需要进行项目目录的优化调整:

在项目主目录下New一个Python Package为apps,保存项目中所有的app,并将自动生成的users移动到apps目录下;

再在主目录下创建extra_apps包,保存源码经修改的第三方包;

创建目录media,用于保存文件和图片等;

创建目录db_tools,用于保存数据库初始化的脚本等。


为了以后开发更加方便,可以将apps和extra_apps右键 → Mark Directory as → Sources Root,完成后文件夹颜色会发生改变。


还需要将apps和extra_apps加入到settings.py的根目录参数中,如下:

import os
import sys
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
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'))

二、数据模型设计

在进行需求分析之后,即可设计数据模型,即数据表。在创建数据模型之前,需要创建所需的app,项目中需要的app包括商品goods、交易trade、用户users、操作user_operation(是为了防止相互引用而建立的)。


创建app可以直接点击导航栏Tools → Run manage.py Task,在命令行中分别输入startapp goods、startapp trade和startapp user_operation创建对应的app,这比手动创建文件效率高很多。创建好之后,将3个目录移动到apps目录之下即可。


此时即可在每个app下分别创建数据模型。


为了保存数据,在进行删除操作时不真正删除数据,所有模型都增加一个属性is_delete,为布尔型值,为False时表示未删除,为True时表示被删除,以此来保证数据的安全。

1.用户数据模型设计

apps/users/models下创建数据模型如下:

from datetime import datetime
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
    '''用户'''
    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=(('male', u'男'), ('female', u'女')), default='female',
                              verbose_name='性别')
    mobile = models.CharField(max_length=11, verbose_name='电话')
    email = models.CharField(max_length=50, null=True, blank=True, verbose_name='邮箱')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '用户'
        verbose_name_plural = '用户'
    def __str__(self):
        return self.name
class VerifyCode(models.Model):
    code = models.CharField(max_length=10, verbose_name='验证码')
    mobile = models.CharField(max_length=11, verbose_name='电话')
    add_time = models.DateField(default=datetime.now, verbose_name='添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '短信验证码'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.code

此时定义的用户还未替换系统自定义的用户,还需要在settings.py中进行设置:

ALLOWED_HOSTS = []
AUTH_USER_MODEL = 'users.UserProfile'

2.商品数据模型设计

商品包括商品分类(分为3个层次,具有从属关系)、品牌名、商品、商品轮播图、轮播商品等实体,goods/models.py建立模型如下:

from datetime import datetime
from django.db import models
from DjangoUeditor.models import UEditorField
# Create your models here.
class GoodsCategory(models.Model):
    '''商品分类'''
    CATEGORY_TYPE = (
        (1, '一级类目'),
        (2, '二级类目'),
        (3, '三级类目'),
    )
    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='父类别', related_name='sub_cat', on_delete=models.SET_NULL)
    is_tab = models.BooleanField(default=False, verbose_name='是否导航', help_text='是否导航')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '商品类别'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.name
class GoodsCategoryBrand(models.Model):
    '''品牌名'''
    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='brand/images/')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '品牌'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.name
class Goods(models.Model):
    '''商品'''
    category = models.ForeignKey(GoodsCategory, verbose_name='商品类目', null=True, on_delete=models.SET_NULL)
    goods_sn = models.CharField(max_length=50, default='', verbose_name='商品唯一货号')
    name = models.CharField(max_length=300, 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, blank=True, verbose_name='封面图')
    is_new = models.BooleanField(default=False, verbose_name='是否新品')
    is_home = models.BooleanField(default=False, verbose_name='是否热销')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
class GoodsImage(models.Model):
    '''商品轮播图'''
    goods = models.ForeignKey(Goods, verbose_name='', related_name='商品', null=True, on_delete=models.SET_NULL)
    image = models.ImageField(upload_to='', null=True, blank=True, verbose_name='图片')
    image_url = models.CharField(max_length=300, null=True, blank=True, verbose_name='图片链接')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, 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='商品', null=True, on_delete=models.SET_NULL)
    image = models.ImageField(upload_to='banner', verbose_name='轮播图片')
    index = models.IntegerField(default=0, verbose_name='轮播顺序')
    add_time = models.DateField(default=datetime.now, verbose_name='添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '轮播商品'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.goods.name

在建立商品模型时,需要用到百度的富文本编辑器UEditor,但是由于官方的Django UEditor停止维护、不再支持Python3,因此需要自行下载,可点击https://download.csdn.net/download/CUFEECR/12641702https://github.com/twz915/DjangoUeditor3/下载并解压后,将DjangoEeditor目录放入项目的extra_apps目录下,并在settings.py中添加app如下:

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps.users.apps.UsersConfig',
    'goods',
    'trade',
    'user_operation',
    'DjangoUeditor'
]

当然,也可以如下:

INSTALLED_APPS = [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps.users.apps.UsersConfig',
    'goods.apps.GoodsConfig',
    'trade.apps.TradeConfig',
    'user_operation.apps.UserOperationConfig',
    'DjangoUeditor'
]

效果是一样的,这里采用后者。

3.交易数据模型设计

交易涉及到购物车、订单等实体。

购物车中如果商品多次加入购物车,只有1条数据,其数量增加;

点击结算之后,购物车数量减少、结算数量增加。

trade/models.py建立购物车和订单模型如下:

from datetime import datetime
from django.db import models
from django.contrib.auth import get_user_model  # from user.models import UserProfile
from goods.models import Goods
User = get_user_model()
# Create your models here.
class ShoppingCart(models.Model):
    '''购物车'''
    user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL)
    goods = models.ForeignKey(Goods, verbose_name='商品', null=True, on_delete=models.SET_NULL)
    goods_num = models.IntegerField(default=0, verbose_name='商品数量')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '购物车'
        verbose_name_plural = verbose_name
    def __str__(self):
        return '%s(%d)'.format(self.goods.name, self.goods_num)
class OrderInfo(models.Model):
    '''订单信息'''
    ORDER_STATUS = (
        ('success', '成功'),
        ('cancel', '取消'),
        ('paying', '待支付'),
    )
    user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL)
    order_sn = models.CharField(max_length=30, unique=True, verbose_name='订单号')
    trade_no = models.CharField(max_length=50, unique=True, null=True, blank=True, verbose_name='交易号')
    pay_status = models.CharField(max_length=100, choices=ORDER_STATUS, verbose_name='订单状态')
    pay_script = models.CharField(max_length=11, 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.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
class OrderGoods(models.Model):
    '''订单商品详情'''
    order = models.ForeignKey(OrderInfo, verbose_name='订单信息', null=True, on_delete=models.SET_NULL)
    goods = models.ForeignKey(Goods, verbose_name='商品', null=True, on_delete=models.SET_NULL)
    goods_num = models.IntegerField(default=0, verbose_name='商品数量')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '订单商品'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.order.order_sn

在定义购物车模型、需要导入用户模型时,因为假如是第三方项目,不知道其定义的具体用户模型和存放目录,所以from user.models import UserProfile具有一定的局限性因为之前已经将UserProfile注册到系统用户,所以可以直接用Django提供的函数get_user_model()来获取用户,这样显得更加灵活。

4.用户操作数据模型设计

最典型的操作是收藏、添加收货地址和留言。

user_operation/models.py建立模型如下:

from datetime import datetime
from django.db import models
from django.contrib.auth import get_user_model
from goods.models import Goods
User = get_user_model()
# Create your models here.
class UserFav(models.Model):
    '''用户收藏'''
    user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL)
    goods = models.ForeignKey(Goods, verbose_name='商品', null=True, on_delete=models.SET_NULL)
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '用户收藏'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.user.name
class UserLeavingMessage(models.Model):
    '''用户留言'''
    MESSAGE_CHOICES = (
        (1, '留言'),
        (2, '投诉'),
        (3, '询问'),
        (4, '售后'),
        (5, '求购'),
    )
    user = models.ForeignKey(User, verbose_name='用户', null=True, on_delete=models.SET_NULL)
    message_type = models.IntegerField(default=1, choices=MESSAGE_CHOICES, verbose_name='留言类型',
                                help_text='留言类型: 1(留言), 2(投诉), 3(询问),4(售后), 5(求购)')
    subject = models.CharField(max_length=80, default='', verbose_name='主题')
    message = models.TextField(default='', verbose_name='留言内容', help_text='留言内容')
    file = models.FileField(verbose_name='上传的文件', help_text='上传的文件')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, 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='用户', null=True, on_delete=models.SET_NULL)
    district = models.CharField(max_length=50, default='', 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, default='', verbose_name='联系电话')
    add_time = models.DateField(default=datetime.now, verbose_name=u'添加时间')
    is_delete = models.BooleanField(default=False, verbose_name='是否删除')
    class Meta:
        verbose_name = '收货地址'
        verbose_name_plural = verbose_name
    def __str__(self):
        return self.address


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
9天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
87 44
|
5天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发
|
10天前
|
安全 数据库 开发者
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第26天】本文详细介绍了如何在Django框架下进行全栈开发,包括环境安装与配置、创建项目和应用、定义模型类、运行数据库迁移、创建视图和URL映射、编写模板以及启动开发服务器等步骤,并通过示例代码展示了具体实现过程。
26 2
|
15天前
|
JavaScript 前端开发 测试技术
组件化开发:创建可重用的Vue组件
【10月更文挑战第21天】组件化开发:创建可重用的Vue组件
23 1
|
16天前
|
JavaScript 前端开发
vue全局公共组件自动引入并注册,开发效率直接起飞!
【10月更文挑战第14天】vue全局公共组件自动引入并注册,开发效率直接起飞!
39 1
|
24天前
|
存储 前端开发 中间件
vue3之vite配置vite-plugin-mock使用mock轻松创建模拟数据提高开发效率
vue3之vite配置vite-plugin-mock使用mock轻松创建模拟数据提高开发效率
181 0
|
24天前
|
存储 JSON JavaScript
Vue.js开发中基于localStorage与sessionStorage的本地存储利器:Vue-ls插件使用详解
Vue.js开发中基于localStorage与sessionStorage的本地存储利器:Vue-ls插件使用详解
38 0
|
24天前
|
设计模式 JavaScript 开发工具
Vue开发中使用好钩子方法(hook method)可以使你的代码更加模块化和可维护
Vue开发中使用好钩子方法(hook method)可以使你的代码更加模块化和可维护
17 0
|
13天前
|
安全 数据库 C++
Python Web框架比较:Django vs Flask vs Pyramid
Python Web框架比较:Django vs Flask vs Pyramid
25 1
|
2月前
|
机器学习/深度学习 人工智能 算法
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
植物病害识别系统。本系统使用Python作为主要编程语言,通过收集水稻常见的四种叶片病害图片('细菌性叶枯病', '稻瘟病', '褐斑病', '稻瘟条纹病毒病')作为后面模型训练用到的数据集。然后使用TensorFlow搭建卷积神经网络算法模型,并进行多轮迭代训练,最后得到一个识别精度较高的算法模型,然后将其保存为h5格式的本地模型文件。再使用Django搭建Web网页平台操作界面,实现用户上传一张测试图片识别其名称。
116 22
植物病害识别系统Python+卷积神经网络算法+图像识别+人工智能项目+深度学习项目+计算机课设项目+Django网页界面
下一篇
无影云桌面