(專案)生鮮超市(二)
三、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 'users.apps.UsersConfig', 8 'users', 9 'goods', 10 'trade', 11 'user_operation', 12 'rest_framework', 13 'xadmin', 14 'crispy_forms', 15 'DjangoUeditor' 16 ]
然後在settings.py中配置檔案media上傳的路徑:
1 MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
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