三、Model设计
1、项目初始化
该项目使用Django Rest Framework完成后台功能,需要安装djangorestframework包及其相关的依赖包,pillow库是图片处理的库,在虚拟环境中安装如下包:
- pip install djangorestframework
- pip install markdown
- pip install django-filter
- pip install pillow
- pip install pymysql
安装完成之后,在settings.py中进行数据库的配置,在这之前需要在数据库中创建一个mxshop数据库:
1 DATABASES = {
2 'default': {
3 'ENGINE': 'django.db.backends.mysql',
4 'NAME': 'mxshop',
5 'USER': 'root',
6 'PASSWORD': 'python',
7 'HOST': '192.168.161.129',
8 'PORT': 3306,
9 'OPTIONS':{'init_command': 'SET default_storage_engine=INNODB;'}
10 }
11 }
然后安装对应python版本的mysqlclient,下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient,下载好之后放到项目根目录下,直接
pip install mysqlclient-1.3.13-cp36-cp36m-win_amd64.whl
然后在__init__.py文件中添加代码:
1 import pymysql 2 3 pymysql.install_as_MySQLdb()
现在完善项目的目录结构,在项目根目录下新建两个package包:
- extra_apps(扩展的源码包)
- apps(放项目创建的app)
新建两个文件夹:
- media(上传的文件)
- db_tools(数据相关)
将extra_apps和apps两个包标记为sources root,然后在settings.py中添加文件访问路径:
1 import os 2 import sys 3 4 # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 5 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 6 sys.path.insert(0, BASE_DIR) 7 sys.path.insert(0, os.path.join(BASE_DIR, 'apps')) 8 sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
现在项目的目录结构如下:

2、model设计
该项目需要创建四个app,之前在创建django项目的时候已经创建了users用户app了,现在创建其余三个:
- startapp goods(商品相关)
- startapp trade(交易相关)
- startapp user_operation(用户操作相关)
将这四个app移动到项目目录的apps包下:

将xadmin的源码包和富文本DjangoUeditor的源码包放到extra_apps包下面,具体的安装方式在我的博客在线教育平台中有详细介绍,这里不再赘述:

然后将四个app和xadmin、DjangoUeditor添加到settings.py的INSTALLED_APPS中:
1 INSTALLED_APPS = [ 2 'django.contrib.auth', 3 'django.contrib.contenttypes', 4 'django.contrib.sessions', 5 'django.contrib.messages', 6 'django.contrib.staticfiles', 7 'django.contrib.admin', 8 'users', 9 'goods', 10 'trade', 11 'user_operation', 12 'xadmin', 13 'crispy_forms', 14 'DjangoUeditor', 15 'rest_framework' 16 ]
然后在settings.py中配置文件media文件上传的路径:
1 # 设置上传文件的路径 2 MEDIA_URL="/media/" 3 MEDIA_ROOT = os.path.join(BASE_DIR, "media")
配置上传文件的url:
1 from django.views.static import serve
2
3 from MxShop.settings import MEDIA_ROOT
4
5 urlpatterns = [
6 path('media/<path:path>', serve, {'document_root': MEDIA_ROOT}),
7 ]
2.1 users的model设计
1 from datetime import datetime
2
3 from django.db import models
4 from django.contrib.auth.models import AbstractUser
5
6 # Create your models here.
7
8
9 class UserProfile(AbstractUser):
10 """用户信息"""
11
12 GENDER_CHOICES = (
13 ('male', '男'),
14 ('female', '女')
15 )
16
17 name = models.CharField('姓名', max_length=30, null=True, blank=True)
18 birthday = models.DateField('出生年月', null=True, blank=True)
19 gender = models.CharField('性别', choices=GENDER_CHOICES, max_length=6, default='male')
20 mobile = models.CharField('电话', max_length=11)
21 email = models.EmailField('邮箱', max_length=100, null=True, blank=True)
22
23 class Meta:
24 verbose_name = '用户信息'
25 verbose_name_plural = verbose_name
26
27 def __str__(self):
28 return self.username
29
30
31 class VerifyCode(models.Model):
32 """短信验证码"""
33
34 code = models.CharField('验证码', max_length=10)
35 mobile = models.CharField('电话', max_length=11)
36 add_time = models.DateTimeField('添加时间', default=datetime.now)
37
38 class Meta:
39 verbose_name = '短信验证码'
40 verbose_name_plural = verbose_name
41
42 def __str__(self):
43 return self.code
UserProfile继承的是django的AbstractUser,需要在settings.py中进行配置:
1 AUTH_USER_MODEL = 'users.UserProfile'
2.2 goods的model设计
依照下面的页面进行商品的model设计:


1 from datetime import datetime
2
3 from django.db import models
4 from DjangoUeditor.models import UEditorField
5
6
7 # Create your models here.
8
9
10 class GoodsCategory(models.Model):
11 """商品分类"""
12
13 CATEGORY_CHOICES = (
14 (1, '一级类目'),
15 (2, '二级类目'),
16 (3, '三级类目'),
17 )
18
19 name = models.CharField('类别名', max_length=30, default='', help_text='类别名')
20 code = models.CharField('类别code', max_length=30, default='', help_text='类别code')
21 desc = models.TextField('类别描述', default='', help_text='类别描述')
22 category_type = models.IntegerField('类目级别', choices=CATEGORY_CHOICES, help_text='类目级别')
23 parent_category = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, verbose_name='父类目级别',
24 help_text='父类目级别', related_name='sub_cat')
25 is_tab = models.BooleanField('是否导航', default=False, help_text='是否导航')
26 add_time = models.DateTimeField('添加时间', default=datetime.now)
27
28 class Meta:
29 verbose_name = '商品类别'
30 verbose_name_plural = verbose_name
31
32 def __str__(self):
33 return self.name
34
35
36 class GoodsCategoryBrand(models.Model):
37 """商品宣传商标"""
38 category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='brands', null=True, blank=True,
39 verbose_name="商品类目")
40 name = models.CharField("品牌名", default="", max_length=30, help_text="品牌名")
41 desc = models.TextField("品牌描述", default="", max_length=200, help_text="品牌描述")
42 image = models.ImageField(max_length=200, upload_to="brands/images/")
43 add_time = models.DateTimeField("添加时间", default=datetime.now)
44
45 class Meta:
46 verbose_name = "宣传品牌"
47 verbose_name_plural = verbose_name
48 db_table = "goods_goodsbrand"
49
50 def __str__(self):
51 return self.name
52
53
54 class Goods(models.Model):
55 """商品"""
56
57 category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='商品类目')
58 goods_sn = models.CharField('商品唯一货号', max_length=50, default='')
59 name = models.CharField('商品名', max_length=100)
60 click_nums = models.IntegerField('点击数', default=0)
61 sold_num = models.IntegerField("商品销售量", default=0)
62 fav_num = models.IntegerField("收藏数", default=0)
63 goods_num = models.IntegerField("库存数", default=0)
64 market_price = models.FloatField("市场价格", default=0)
65 shop_price = models.FloatField("本店价格", default=0)
66 goods_brief = models.CharField('商品简短描述', max_length=500)
67 goods_desc = UEditorField(verbose_name="商品描述", imagePath="goods/images/", width=1000, height=300,
68 filePath="goods/files/", default='')
69 ship_free = models.BooleanField('是否承担运费', default=True)
70 goods_front_image = models.ImageField(upload_to='goods/images/', null=True, blank=True, verbose_name='首页封面图')
71 is_new = models.BooleanField('是否新品', default=False) # 首页新品展示
72 is_hot = models.BooleanField('是否热销', default=False) # 商品详情页的热卖商品
73 add_time = models.DateTimeField('添加时间', default=datetime.now)
74
75 class Meta:
76 verbose_name = '商品信息'
77 verbose_name_plural = verbose_name
78
79 def __str__(self):
80 return self.name
81
82
83 class GoodsImage(models.Model):
84 """商品轮播图"""
85
86 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品', related_name='images')
87 image = models.ImageField(upload_to='goods/images/', verbose_name='图片', null=True, blank=True)
88 add_time = models.DateTimeField('添加时间', default=datetime.now)
89
90 class Meta:
91 verbose_name = '商品轮播图'
92 verbose_name_plural = verbose_name
93
94 def __str__(self):
95 return self.goods.name
96
97
98 class Banner(models.Model):
99 """首页轮播图"""
100
101 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
102 image = models.ImageField(upload_to='banners/images/', verbose_name='轮播图')
103 index = models.IntegerField('轮播顺序', default=0)
104 add_time = models.DateTimeField('添加时间', default=datetime.now)
105
106 class Meta:
107 verbose_name = '首页轮播图'
108 verbose_name_plural = verbose_name
109
110 def __str__(self):
111 return self.goods.name
112
113
114 class IndexAd(models.Model):
115 """商品广告"""
116 category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='category', verbose_name="商品类目")
117 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, related_name='goods')
118
119 class Meta:
120 verbose_name = '首页广告'
121 verbose_name_plural = verbose_name
122
123 def __str__(self):
124 return self.goods.name
125
126
127 class HotSearchWords(models.Model):
128 """热搜词"""
129
130 keywords = models.CharField('热搜词', max_length=20, default='')
131 index = models.IntegerField('排序', default=0)
132 add_time = models.DateTimeField('添加时间', default=datetime.now)
133
134 class Meta:
135 verbose_name = '热搜排行'
136 verbose_name_plural = verbose_name
137
138 def __str__(self):
139 return self.keywords
2.3 trade的model设计
1 from datetime import datetime
2
3 from django.db import models
4 from django.contrib.auth import get_user_model
5
6 from goods.models import Goods
7
8
9 # get_user_model会去setting中找AUTH_USER_MODEL
10 User = get_user_model()
11
12 # Create your models here.
13
14
15 class ShoppingCart(models.Model):
16 """购物车"""
17
18 user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
19 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
20 nums = models.IntegerField('购买数量', default=0)
21 add_time = models.DateTimeField('添加时间', default=datetime.now)
22
23 class Meta:
24 verbose_name = '购物车'
25 verbose_name_plural = verbose_name
26 unique_together = ('user', 'goods')
27
28 def __str__(self):
29 return self.goods.name
30
31
32 class OrderInfo(models.Model):
33 """订单信息"""
34
35 ORDER_STATUS = (
36 ("TRADE_SUCCESS", "成功"),
37 ("TRADE_CLOSED", "超时关闭"),
38 ("WAIT_BUYER_PAY", "交易创建"),
39 ("TRADE_FINISHED", "交易结束"),
40 ("paying", "待支付"),
41 )
42 PAY_TYPE = (
43 ("alipay", "支付宝"),
44 ("wechat", "微信"),
45 )
46
47 user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
48 order_sn = models.CharField('订单编号', max_length=30, null=True, blank=True, unique=True)
49 nonce_str = models.CharField('随机加密串', max_length=50, null=True, blank=True, unique=True) # 微信支付会用到
50 trade_no = models.CharField('交易号', max_length=100, null=True, blank=True, unique=True) # 支付号交易号
51 pay_status = models.CharField('订单状态', choices=ORDER_STATUS, default='paying', max_length=30)
52 pay_type = models.CharField('支付类型', choices=PAY_TYPE, default='alipay', max_length=10)
53 post_script = models.CharField('订单留言', max_length=200)
54 order_mount = models.FloatField('订单金额', default=0.0)
55 pay_time = models.DateTimeField('支付时间', null=True, blank=True)
56 address = models.CharField('收货地址', max_length=100, default='')
57 singer_name = models.CharField('签收人', max_length=20, default='')
58 singer_mobile = models.CharField('签收电话', max_length=11)
59 add_time = models.DateTimeField('添加时间', default=datetime.now)
60
61 class Meta:
62 verbose_name = '订单信息'
63 verbose_name_plural = verbose_name
64
65 def __str__(self):
66 return str(self.order_sn)
67
68
69 class OrderGoods(models.Model):
70 """订单内商品"""
71
72 order = models.ForeignKey(OrderInfo, on_delete=models.CASCADE, verbose_name='订单信息', related_name='goods')
73 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
74 goods_num = models.IntegerField('商品数量', default=0)
75 add_time = models.DateTimeField('添加时间', default=datetime.now)
76
77 class Meta:
78 verbose_name = '订单商品'
79 verbose_name_plural = verbose_name
80
81 def __str__(self):
82 return str(self.order.order_sn)
2.4 user_operation的model设计
1 from datetime import datetime
2
3 from django.db import models
4 from django.contrib.auth import get_user_model
5
6 from goods.models import Goods
7
8 User = get_user_model()
9
10
11 # Create your models here.
12
13
14 class UserFav(models.Model):
15 """用户收藏"""
16
17 user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
18 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品', help_text='商品id')
19 add_time = models.DateTimeField('添加时间', default=datetime.now)
20
21 class Meta:
22 verbose_name = '用户收藏'
23 verbose_name_plural = verbose_name
24 unique_together = ('user', 'goods')
25
26 def __str__(self):
27 return self.user.username
28
29
30 class UserAddress(models.Model):
31 """收货地址"""
32
33 user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
34 province = models.CharField("省份", max_length=100, default="")
35 city = models.CharField("城市", max_length=100, default="")
36 district = models.CharField("区域", max_length=100, default="")
37 address = models.CharField("详细地址", max_length=100, default="")
38 signer_name = models.CharField("签收人", max_length=100, default="")
39 signer_mobile = models.CharField("电话", max_length=11, default="")
40 add_time = models.DateTimeField("添加时间", default=datetime.now)
41
42 class Meta:
43 verbose_name = "收货地址"
44 verbose_name_plural = verbose_name
45
46 def __str__(self):
47 return self.address
48
49
50 class UserLeavingMessage(models.Model):
51 """用户留言"""
52
53 MESSAGE_CHOICES = (
54 (1, "留言"),
55 (2, "投诉"),
56 (3, "询问"),
57 (4, "售后"),
58 (5, "求购")
59 )
60 user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户")
61 message_type = models.IntegerField("留言类型", default=1, choices=MESSAGE_CHOICES,
62 help_text="留言类型: 1(留言),2(投诉),3(询问),4(售后),5(求购)")
63 subject = models.CharField("主题", max_length=100, default="")
64 message = models.TextField("留言内容", default="", help_text="留言内容")
65 file = models.FileField(upload_to="message/images/", verbose_name="上传的文件", help_text="上传的文件")
66 add_time = models.DateTimeField("添加时间", default=datetime.now)
67
68 class Meta:
69 verbose_name = "用户留言"
70 verbose_name_plural = verbose_name
71
72 def __str__(self):
73 return self.subject
来源:https://www.cnblogs.com/Sweltering/p/10014114.html