目錄
生鮮超市(十) 生鮮超市(十一) 生鮮超市(十二) 生鮮超市(十三)
代碼下載
教程
學習自慕課網-前端vue結合后端DjangoFramework的在線生鮮超市
三、Models設計
3.1.項目初始化
(1)進虛擬環境下安裝
- django2.0.2
- djangorestframework和相關依賴mark,filter
- pillow 圖片處理
pip install djangorestframework pip install -i https://pypi.douban.com/simple django==2.0.2 pip install markdown pip install django-filter
pip install pillow
pip install pymysql
(2)創建項目
- 項目:MxShop
- app:users
interpreter選擇虛擬環境里面的python.exe
(3)Mysql的配置
settings中設置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'mxshop', #數據庫名字 'USER': 'root', #賬號 'PASSWORD': '123456', #密碼 'HOST': '127.0.0.1', #IP 'PORT': '3306', #端口 #這里引擎用innodb(默認myisam) #因為后面第三方登錄時,要求引擎為INNODB # 'OPTIONS':{'init_command': 'SET storage_engine=INNODB'}, #這樣設置會報錯,改為 "OPTIONS":{"init_command":"SET default_storage_engine=INNODB;"} } }
安裝Mysqlclient
下載地址:
https://www.lfd.uci.edu/~gohlke/pythonlibs/
安裝
pip install mysqlclient-1.3.12-cp36-cp36m-win_amd64
__init__.py添加代碼:
import pymysql pymysql.install_as_MySQLdb()
(4)項目目錄結構搭建
新建兩個python package
- extra_apps (擴展的源碼包)
- apps (放所有app)
新建兩個文件夾
- media (保存圖片)
- db_tools (數據庫相關)
把extra_apps和apps標記為sources root,然后settings中也要加路徑
#settings.py import sys 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'))
現在項目目錄如下:
3.2.users models設計
(1)創建三個app
- goods 商品
- trade 交易
- user_operation 用戶操作
(2)users/models.py
# users/models.py __author__ = 'derek' from datetime import datetime from django.db import models from django.contrib.auth.models import AbstractUser class UserProfile(AbstractUser): """ 用戶信息 """ GENDER_CHOICES = ( ("male", u"男"), ("female", u"女") ) #用戶用手機注冊,所以姓名,生日和郵箱可以為空 name = models.CharField("姓名",max_length=30, null=True, blank=True) birthday = models.DateField("出生年月",null=True, blank=True) gender = models.CharField("性別",max_length=6, choices=GENDER_CHOICES, default="female") mobile = models.CharField("電話",max_length=11) email = models.EmailField("郵箱",max_length=100, null=True, blank=True) 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) mobile = models.CharField("電話",max_length=11) add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "短信驗證" verbose_name_plural = verbose_name def __str__(self): return self.code
要想替換系統的用戶,還要在settings中配置
#settings.py #重載系統的用戶,讓UserProfile生效 AUTH_USER_MODEL = 'users.UserProfile'
(3)這里UserProfile繼承AbstractUser,可以看看AbstractUser的源碼

class AbstractUser(AbstractBaseUser, PermissionsMixin): """ An abstract base class implementing a fully featured User model with admin-compliant permissions. Username and password are required. Other fields are optional. """ username_validator = UnicodeUsernameValidator() username = models.CharField( _('username'), max_length=150, unique=True, help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists."), }, ) first_name = models.CharField(_('first name'), max_length=30, blank=True) last_name = models.CharField(_('last name'), max_length=150, blank=True) email = models.EmailField(_('email address'), blank=True) is_staff = models.BooleanField( _('staff status'), default=False, help_text=_('Designates whether the user can log into this admin site.'), ) is_active = models.BooleanField( _('active'), default=True, help_text=_( 'Designates whether this user should be treated as active. ' 'Unselect this instead of deleting accounts.' ), ) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) objects = UserManager() EMAIL_FIELD = 'email' USERNAME_FIELD = 'username' REQUIRED_FIELDS = ['email'] class Meta: verbose_name = _('user') verbose_name_plural = _('users') abstract = True def clean(self): super().clean() self.email = self.__class__.objects.normalize_email(self.email) def get_full_name(self): """ Return the first_name plus the last_name, with a space in between. """ full_name = '%s %s' % (self.first_name, self.last_name) return full_name.strip() def get_short_name(self): """Return the short name for the user.""" return self.first_name def email_user(self, subject, message, from_email=None, **kwargs): """Send an email to this user.""" send_mail(subject, message, from_email, [self.email], **kwargs)
3.3.goods的model設計
(1)安裝
- xadmin xadmin安裝方法
- DjangoUeditor 富文本編輯器安裝方法
安裝好后把xadmin和DjangoUeditor放到extra_apps目錄下面
(2)把四個app、xadmin和DjangoUeditor添加到 INSTALLED_APPS中
INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'users', 'goods', 'trade', 'user_operation', 'rest_framework', 'xadmin', 'crispy_forms', 'DjangoUeditor' ]
設置media的保存路徑
#settings.py MEDIA_ROOT = os.path.join(BASE_DIR, "media")
(3)商品分類model 設計
class GoodsCategory(models.Model): """ 商品分類 """ CATEGORY_TYPE = ( (1, "一級類目"), (2, "二級類目"), (3, "三級類目"), ) name = models.CharField('類別名',default="", max_length=30,help_text="類別名") code = models.CharField("類別code",default="", max_length=30,help_text="類別code") desc = models.TextField("類別描述",default="",help_text="類別描述") #目錄樹級別 category_type = models.IntegerField("類目級別",choices=CATEGORY_TYPE,help_text="類目級別") # 設置models有一個指向自己的外鍵 parent_category = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, verbose_name="父類目級別", help_text="父目錄", related_name="sub_cat") is_tab = models.BooleanField("是否導航",default=False,help_text="是否導航") add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "商品類別" verbose_name_plural = verbose_name def __str__(self): return self.name
(4)商品model設計
class Goods(models.Model): """ 商品 """ category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name="商品類目") goods_sn = models.CharField("商品唯一貨號",max_length=50, default="") name = models.CharField("商品名",max_length=100,) click_num = models.IntegerField("點擊數",default=0) sold_num = models.IntegerField("商品銷售量",default=0) fav_num = models.IntegerField("收藏數",default=0) goods_num = models.IntegerField("庫存數",default=0) market_price = models.FloatField("市場價格",default=0) shop_price = models.FloatField("本店價格",default=0) goods_brief = models.TextField("商品簡短描述",max_length=500) goods_desc = UEditorField(verbose_name=u"內容", imagePath="goods/images/", width=1000, height=300, filePath="goods/files/", default='') ship_free = models.BooleanField("是否承擔運費",default=True) # 首頁中展示的商品封面圖 goods_front_image = models.ImageField(upload_to="goods/images/", null=True, blank=True, verbose_name="封面圖") # 首頁中新品展示 is_new = models.BooleanField("是否新品",default=False) # 商品詳情頁的熱賣商品,自行設置 is_hot = models.BooleanField("是否熱銷",default=False) add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = '商品信息' verbose_name_plural = verbose_name def __str__(self): return self.name class GoodsImage(models.Model): """ 商品輪播圖 """ goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品", related_name="images") image = models.ImageField(upload_to="", verbose_name="圖片", null=True, blank=True) add_time = models.DateTimeField("添加時間", default=datetime.now) class Meta: verbose_name = '商品輪播' verbose_name_plural = verbose_name def __str__(self): return self.goods.name
(4)首頁商品輪播圖model設計
因為首頁的商品輪播圖片是大圖,跟商品詳情里面的圖片不一樣,所以要單獨寫一個首頁輪播圖model
class Banner(models.Model): """ 首頁輪播的商品 """ goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品") image = models.ImageField(upload_to='banner', verbose_name="輪播圖片") index = models.IntegerField("輪播順序",default=0) add_time = models.DateTimeField("添加時間", default=datetime.now) class Meta: verbose_name = '首頁輪播' verbose_name_plural = verbose_name def __str__(self): return self.goods.name
(5)商品廣告和熱搜model
class HotSearchWords(models.Model): """ 搜索欄下方熱搜詞 """ keywords = models.CharField("熱搜詞",default="", max_length=20) index = models.IntegerField("排序",default=0) add_time = models.DateTimeField("添加時間", default=datetime.now) class Meta: verbose_name = '熱搜排行' verbose_name_plural = verbose_name def __str__(self): return self.keywords

#goods/models.py __author__ = 'derek' from datetime import datetime from django.db import models from DjangoUeditor.models import UEditorField class GoodsCategory(models.Model): """ 商品分類 """ CATEGORY_TYPE = ( (1, "一級類目"), (2, "二級類目"), (3, "三級類目"), ) name = models.CharField('類別名',default="", max_length=30,help_text="類別名") code = models.CharField("類別code",default="", max_length=30,help_text="類別code") desc = models.TextField("類別描述",default="",help_text="類別描述") #目錄樹級別 category_type = models.IntegerField("類目級別",choices=CATEGORY_TYPE,help_text="類目級別") # 設置models有一個指向自己的外鍵 parent_category = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True, verbose_name="父類目級別", help_text="父目錄", related_name="sub_cat") is_tab = models.BooleanField("是否導航",default=False,help_text="是否導航") add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "商品類別" verbose_name_plural = verbose_name def __str__(self): return self.name class GoodsCategoryBrand(models.Model): """ 某一大類下的宣傳商標 """ category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='brands', null=True, blank=True, verbose_name="商品類目") name = models.CharField("品牌名",default="", max_length=30,help_text="品牌名") desc = models.TextField("品牌描述",default="", max_length=200,help_text="品牌描述") image = models.ImageField(max_length=200, upload_to="brands/") add_time = models.DateTimeField("添加時間",default=datetime.now) 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, on_delete=models.CASCADE, verbose_name="商品類目") goods_sn = models.CharField("商品唯一貨號",max_length=50, default="") name = models.CharField("商品名",max_length=100,) click_num = models.IntegerField("點擊數",default=0) sold_num = models.IntegerField("商品銷售量",default=0) fav_num = models.IntegerField("收藏數",default=0) goods_num = models.IntegerField("庫存數",default=0) market_price = models.FloatField("市場價格",default=0) shop_price = models.FloatField("本店價格",default=0) goods_brief = models.TextField("商品簡短描述",max_length=500) goods_desc = UEditorField(verbose_name=u"內容", imagePath="goods/images/", width=1000, height=300, filePath="goods/files/", default='') ship_free = models.BooleanField("是否承擔運費",default=True) # 首頁中展示的商品封面圖 goods_front_image = models.ImageField(upload_to="goods/images/", null=True, blank=True, verbose_name="封面圖") # 首頁中新品展示 is_new = models.BooleanField("是否新品",default=False) # 商品詳情頁的熱賣商品,自行設置 is_hot = models.BooleanField("是否熱銷",default=False) add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = '商品信息' verbose_name_plural = verbose_name def __str__(self): return self.name class GoodsImage(models.Model): """ 商品輪播圖 """ goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品", related_name="images") image = models.ImageField(upload_to="", verbose_name="圖片", null=True, blank=True) add_time = models.DateTimeField("添加時間", default=datetime.now) class Meta: verbose_name = '商品輪播' verbose_name_plural = verbose_name def __str__(self): return self.goods.name class Banner(models.Model): """ 首頁輪播的商品 """ goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品") image = models.ImageField(upload_to='banner', verbose_name="輪播圖片") index = models.IntegerField("輪播順序",default=0) add_time = models.DateTimeField("添加時間", default=datetime.now) class Meta: verbose_name = '首頁輪播' verbose_name_plural = verbose_name def __str__(self): return self.goods.name class IndexAd(models.Model): """ 商品廣告 """ category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, related_name='category',verbose_name="商品類目") goods =models.ForeignKey(Goods, on_delete=models.CASCADE, related_name='goods') 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) index = models.IntegerField("排序",default=0) add_time = models.DateTimeField("添加時間", default=datetime.now) class Meta: verbose_name = '熱搜排行' verbose_name_plural = verbose_name def __str__(self): return self.keywords
3.4.trade交易的model設計
trade/models.py
# trade/models.py __author__ = 'derek' from datetime import datetime from django.db import models from goods.models import Goods # get_user_model方法會去setting中找AUTH_USER_MODEL from django.contrib.auth import get_user_model User = get_user_model() # Create your models here. class ShoppingCart(models.Model): """ 購物車 """ user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用戶") goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品") nums = models.IntegerField("購買數量",default=0) add_time = models.DateTimeField(default=datetime.now, verbose_name="添加時間") class Meta: verbose_name = '購物車喵' verbose_name_plural = verbose_name unique_together = ("user", "goods") 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, on_delete=models.CASCADE, verbose_name="用戶") #訂單號唯一 order_sn = models.CharField("訂單編號",max_length=30, null=True, blank=True, unique=True) # 微信支付會用到 nonce_str = models.CharField("隨機加密串",max_length=50, null=True, blank=True, unique=True) # 支付寶交易號 trade_no = models.CharField("交易號",max_length=100, unique=True, null=True, blank=True) #支付狀態 pay_status = models.CharField("訂單狀態",choices=ORDER_STATUS, default="paying", max_length=30) # 訂單的支付類型 pay_type = models.CharField("支付類型",choices=PAY_TYPE, default="alipay", max_length=10) post_script = models.CharField("訂單留言",max_length=200) order_mount = models.FloatField("訂單金額",default=0.0) pay_time = models.DateTimeField("支付時間",null=True, blank=True) # 用戶信息 address = models.CharField("收貨地址",max_length=100, default="") signer_name = models.CharField("簽收人",max_length=20, default="") singer_mobile = models.CharField("聯系電話",max_length=11) add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "訂單信息" verbose_name_plural = verbose_name def __str__(self): return str(self.order_sn) class OrderGoods(models.Model): """ 訂單內的商品詳情 """ # 一個訂單對應多個商品 order = models.ForeignKey(OrderInfo, on_delete=models.CASCADE, verbose_name="訂單信息", related_name="goods") # 兩個外鍵形成一張關聯表 goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品") goods_num = models.IntegerField("商品數量",default=0) add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "訂單商品" verbose_name_plural = verbose_name def __str__(self): return str(self.order.order_sn)
3.5.用戶操作的model設計
user_operation/models.py
# user_operation/models.py __author__ = 'derek' from datetime import datetime from django.db import models from goods.models import Goods from django.contrib.auth import get_user_model User = get_user_model() class UserFav(models.Model): """ 用戶收藏操作 """ user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用戶") goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name="商品", help_text="商品id") add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = '用戶收藏' verbose_name_plural = verbose_name unique_together = ("user", "goods") def __str__(self): return self.user.username class UserAddress(models.Model): """ 用戶收貨地址 """ user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用戶" ) province = models.CharField("省份",max_length=100, default="") city = models.CharField("城市",max_length=100, default="") district = models.CharField("區域",max_length=100, default="") address = models.CharField("詳細地址",max_length=100, default="") signer_name = models.CharField("簽收人",max_length=100, default="") signer_mobile = models.CharField("電話",max_length=11, default="") add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "收貨地址" verbose_name_plural = verbose_name def __str__(self): return self.address class UserLeavingMessage(models.Model): """ 用戶留言 """ MESSAGE_CHOICES = ( (1, "留言"), (2, "投訴"), (3, "詢問"), (4, "售后"), (5, "求購") ) user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用戶") 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="") message = models.TextField("留言內容",default="",help_text="留言內容") file = models.FileField(upload_to="message/images/", verbose_name="上傳的文件", help_text="上傳的文件") add_time = models.DateTimeField("添加時間",default=datetime.now) class Meta: verbose_name = "用戶留言" verbose_name_plural = verbose_name def __str__(self): return self.subject