zoukankan      html  css  js  c++  java
  • 【Vue+DRF 生鲜电商】环境搭建和模型设计(一)

    1. 环境搭建

    1.1 Python 虚拟环境

    mkdir MxShop
    
    # 创建虚拟环境,修改为豆瓣源
    pipenv install
    

    1.2 Vue 环境

    # 安装 node.js  https://nodejs.org/en/
    
    # 安装 nrm,并切换为淘宝源
    npm i nrm -g    # 全局安装
    nrm ls  # 查看当前可用镜像源地址
    nrm use taobao  # 切换镜像源为 淘宝,速度会快很多
    
    C:Usershj>nrm ls
    
      npm -------- https://registry.npmjs.org/
      yarn ------- https://registry.yarnpkg.com/
      cnpm ------- http://r.cnpmjs.org/
    * taobao ----- https://registry.npm.taobao.org/
      nj --------- https://registry.nodejitsu.com/
      npmMirror -- https://skimdb.npmjs.com/registry/
      edunpm ----- http://registry.enpmjs.org/
    
    # 安装依赖
    npm install
    
    # 运行 vue 项目
    npm run dev
    

    1.3 项目环境

    1.3.1 创建项目

    # 安装 Django
    pipenv install django==2.0.2 --skip-lock
    
    # 创建项目,使用 pycharm 创建新的 Django 项目
    项目名称:MxShop
    app:users
    # 不使用 Django 自带的 admin,而是 xadmin,在使用 pycharm 安装时不勾选 Enable Django admin
    

    其他模块安装:

    pipenv install djangorestframework
    pipenv install markdown
    pipenv install django-filter
    
    pipenv install pillow   # 图片处理
    pipenv install pymysql
    

    1.3.2 配置项目结构

    项目根目录分部创建:

    • appsPython 包文件
    • extra_appsPython 包文件
    • media:文件夹
    • db_tools:文件夹

    并将 apps、extra_apps 标记为 sources rootpycharm 中鼠标右键选择相应文件夹,选择 Mark Directory as -- sources root),并在 settings 配置好路径:

    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'))
    

    配置上面后,将 users 拷贝到 apps,项目整体结构如下图所示:

    settings 中添加 djangorestframework

    INSTALLED_APPS = [
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'users.apps.UsersConfig',
    
        'rest_framework',   # 新增
    ]
    

    1.3.3 配置 MySQL 数据库

    1、MxShop/__init__.py

    import pymysql
    
    pymysql.install_as_MySQLdb()
    

    2、MxShop/settings.py

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'mxshop',
            'USER': 'root',
            'PASSWORD': 'root',
            'HOST': '192.168.131.131',
            'PORT': '3306',
            'OPTIONS': {
            #这里引擎用innodb(默认myisam)
            #因为后面第三方登录时,要求引擎为INNODB
                'init_command': 'SET default_storage_engine=INNODB;'
            }
        }
    }
    

    踩坑:运行项目时出现:django.core.exceptions.ImproperlyConfigured: mysqlclient 1.3.13 or newer is required; you have 0.9.3.

    解决办法,在 MxShop/__init__.py 中添加:

    import pymysql
    
    # 新增
    pymysql.version_info = (1, 3, 13, "final", 0)
    pymysql.install_as_MySQLdb()
    

    1.4 安装 xadmin 和 djangoUEditor

    1.4.1 富文本编辑器Ueditor

    https://github.com/twz915/DjangoUeditor3/

    下载源码,解压后将其拷贝至项目目录下,

    # * 方法一:将github整个源码包下载下来,在命令行运行:
    	python setup.py install
        
    # * 方法二:使用pip工具在命令行运行(推荐)(有可能会出错):
        pip install DjangoUeditor	
    

    将 app 添加到 settings 中:

    INSTALLED_APPS = [
        'DjangoUeditor3',
    ]
    

    配置路由 Projects/urls.py

    path('ueditor/',include('DjangoUeditor.urls' )),
    

    使用

    models.py 中:

    from DjangoUeditor.models import UEditorField
    
    class Goods(models.Model):
        """商品"""
        goods_desc = UEditorField(verbose_name=u"内容", imagePath="goods/images/", width=1000, height=300,
    

    1.4.2 xadmin

    源码安装

    源码安装的好处在于可以在本地修改源码(自定义定制)。

    1、下载源码包:

    • 官方源码有一些小Bug 建议下载 mtianyan 修改后的 xadmin 版本:https://github.com/mtianyan/xadmin_django2.0.1
    • 官方:https://github.com/sshwsfc/xadmin/tree/django2

    2、将其拷贝到项目相应目录中:

    比如下图中的 extra_apps 中,并将 extra_apps 标记为 Sources Root

    3、安装依赖包:

    pip install django-crispy-forms
    django-formtools
    future
    six
    httplib2
    django-import-export
    

    4、注册 xadmin

    # settings.py
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'users.apps.UsersConfig',
    
        'xadmin',
        'crispy_forms',
        'django_filters',
    ]
    

    5、配置路由 Projects/urls.py

    from django.urls import path, include
    
    import xadmin
    
    urlpatterns = [
        # path('admin/', admin.site.urls),
    
        path('xadmin/', xadmin.site.urls),
        path('ueditor/', include('DjangoUeditor.urls')),
    ]
    

    6、迁移数据库:

    # 执行命令
    python manage.py makemigrations
    python manage.py migrate
    
    # 创建超级用户
    python manage.py createsuperuser
    python manage.py runserver
    

    参考文章

    • https://www.cnblogs.com/derek1184405959/p/8592800.html
    • https://blog.csdn.net/soulwyb/article/details/86036176

    1.5 Media 配置

    1、settings.py

    # 设置上传文件路径
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    

    2、在 media/ 中分别创建目录:banner、brands、goods、message,用于保存上传文件。

    3、配置路由 Projects/urls.py

    from django.urls import path, include
    from django.views.static import serve
    
    import xadmin
    from MxShop.settings import MEDIA_ROOT
    
    urlpatterns = [
        # path('admin/', admin.site.urls),
    
        path('xadmin/', xadmin.site.urls),
        path('ueditor/', include('DjangoUeditor.urls')),
        path('media/<path:path>', serve, {'document_root': MEDIA_ROOT}),
    ]
    

    2. 模型设计

    创建三个 app

    • goods:商品
    • trade:贸易
    • user_operation:用户操作
    python manage.py startapp goods
    

    2.1 用户模型

    users/models.py

    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 VerifyCord(models.Model):
        """短信验证码表"""
        code = models.CharField("验证码", max_length=10)
        mobile = models.CharField("电话", max_length=11)
        add_time = models.DateTimeField("添加时间", auto_now_add=True)
    
        class Meta:
            verbose_name = '短信验证'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.code
    

    2.2 商品模型

    goods/models.py

    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='类目级别')
        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('添加时间', auto_now_add=True)
    
        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("添加时间", auto_now_add=True)
    
        class Meta:
            verbose_name = "宣传品牌"
            verbose_name_plural = verbose_name
            db_table = "goods_goodsbrand"
    
        def __str__(self):
            return self.name
    
    
    class Goods(models.Model):
        """商品"""
        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('添加时间', auto_now_add=True)
    
        category = models.ForeignKey(GoodsCategory, on_delete=models.CASCADE, verbose_name='商品类目')
    
        class Meta:
            verbose_name = '商品'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class GoodsImage(models.Model):
        """商品轮播图"""
        image = models.ImageField(upload_to='', verbose_name='图片', null=True, blank=True)
        add_time = models.DateTimeField('添加时间', auto_now_add=True)
    
        goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品', related_name='images')
    
        class Meta:
            verbose_name = '商品轮播图'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.goods.name
    
    
    class Banner(models.Model):
        """首页商品轮播图"""
        image = models.ImageField(upload_to='banner', verbose_name='轮播图片')
        index = models.IntegerField('轮播顺序', default=0)
        add_time = models.DateTimeField('添加时间', auto_now_add=True)
    
        goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
    
        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('添加时间', auto_now_add=True)
    
        class Meta:
            verbose_name = '热搜排行'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.keywords
    

    2.3 交易模型

    trade/models.py

    from django.db import models
    from django.contrib.auth import get_user_model
    
    # get_user_model方法会去setting中找AUTH_USER_MODEL
    from goods.models import Goods
    
    User = get_user_model()
    
    
    class ShoppingCart(models.Model):
        """购物车"""
        nums = models.IntegerField('购买数量', default=0)
    
        user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='用户')
        goods = models.ForeignKey(Goods, on_delete=models.CASCADE, verbose_name='商品')
        add_time = models.DateTimeField(verbose_name="添加时间", auto_now_add=True)
    
        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", "微信"),
        )
    
        # 订单号唯一
        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("添加时间", auto_now_add=True)
    
        user = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="用户")
    
        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("添加时间", auto_now_add=True)
    
        class Meta:
            verbose_name = "订单商品"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return str(self.order.order_sn)
    

    2.4 用户操作模型

    user_operation/models.py

    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("添加时间", auto_now_add=True)
    
        class Meta:
            verbose_name = '用户收藏'
            verbose_name_plural = verbose_name
            unique_together = ("user", "goods")
    
        def __str__(self):
            return self.user.name
    
    
    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("添加时间", auto_now_add=True)
    
        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("添加时间", auto_now_add=True)
    
        class Meta:
            verbose_name = "用户留言"
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.subject
    
  • 相关阅读:
    _status()函数
    _clear87()函数
    _clear87()函数
    _clear87()函数
    _clear87()函数
    南邮NOJ1009 2的n次方
    南邮NOJ2063 突发奇想的茂凯
    南邮NOJ2063 突发奇想的茂凯
    【HDOJ】1297 Children’s Queue
    【HDOJ】2103 Family planning
  • 原文地址:https://www.cnblogs.com/midworld/p/13629660.html
Copyright © 2011-2022 走看看