zoukankan      html  css  js  c++  java
  • Vue+Django REST framework 打造生鲜电商项目(学习笔记二)

    2-2.User Models设计

      拆分功能模块,创建app,分别创建goods,trades,user_operations

    1 startapp goods
    2 startapp trades
    3 startapp user_operations

    将goods,trades,user_operations都移动到apps目录下。

    修改Shop/apps/users/models.py

     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 class UserProfile(AbstractUser):
     8     """
     9     用户
    10     """
    11     name = models.CharField(max_length=30, null=True, blank=True, verbose_name="姓名")
    12     birthday = models.DateField(null=True, blank=True, verbose_name="出生年月")
    13     gender = models.CharField(max_length=6, choices=(("male", u""), ("female", u"")), default="female", verbose_name="性别")
    14     mobile = models.CharField(max_length=11, verbose_name="电话")
    15     email = models.CharField(max_length=100, null=True, blank=True, verbose_name="邮箱")
    16 
    17     class Meta:
    18         verbose_name = "用户"
    19         verbose_name_plural = "用户"
    20 
    21     def __str__(self):
    22         return self.name
    23 
    24 class VerifyCode(models.model):
    25     """
    26     短信验证码
    27     """
    28     code = models.CharField(max_length=10, verbose_name="验证码")
    29     mobile = models.CharField(max_length=11, verbose_name="电话")
    30     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    31 
    32     class Meta:
    33         verbose_name = "短信验证码"
    34         verbose_name_plural = "短信验证码"
    35 
    36     def __str__(self):
    37         return self.code
    View Code

    Django中的class META详解

    再修改Shop/Shop/settings.py,添加 AUTH_USER_MODEL = "users.UserProfile"

      1 """
      2 Django settings for Shop project.
      3 
      4 Generated by 'django-admin startproject' using Django 3.0.5.
      5 
      6 For more information on this file, see
      7 https://docs.djangoproject.com/en/3.0/topics/settings/
      8 
      9 For the full list of settings and their values, see
     10 https://docs.djangoproject.com/en/3.0/ref/settings/
     11 """
     12 
     13 import os
     14 
     15 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
     16 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
     17 
     18 import sys
     19 sys.path.insert(0, BASE_DIR)
     20 sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))
     21 sys.path.insert(0, os.path.join(BASE_DIR, 'extra_apps'))
     22 
     23 
     24 # Quick-start development settings - unsuitable for production
     25 # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
     26 
     27 # SECURITY WARNING: keep the secret key used in production secret!
     28 SECRET_KEY = '#b2zlpse4rsh$z1$7vivv6q04b$rq)@rh==hhrupcv*ayv3s%+'
     29 
     30 # SECURITY WARNING: don't run with debug turned on in production!
     31 DEBUG = True
     32 
     33 ALLOWED_HOSTS = []
     34 
     35 AUTH_USER_MODEL = "users.UserProfile"
     36 
     37 # Application definition
     38 
     39 INSTALLED_APPS = [
     40     'django.contrib.auth',
     41     'django.contrib.contenttypes',
     42     'django.contrib.sessions',
     43     'django.contrib.messages',
     44     'django.contrib.staticfiles',
     45     'apps.users.apps.UsersConfig',
     46 ]
     47 
     48 MIDDLEWARE = [
     49     'django.middleware.security.SecurityMiddleware',
     50     'django.contrib.sessions.middleware.SessionMiddleware',
     51     'django.middleware.common.CommonMiddleware',
     52     'django.middleware.csrf.CsrfViewMiddleware',
     53     'django.contrib.auth.middleware.AuthenticationMiddleware',
     54     'django.contrib.messages.middleware.MessageMiddleware',
     55     'django.middleware.clickjacking.XFrameOptionsMiddleware',
     56 ]
     57 
     58 ROOT_URLCONF = 'Shop.urls'
     59 
     60 TEMPLATES = [
     61     {
     62         'BACKEND': 'django.template.backends.django.DjangoTemplates',
     63         'DIRS': [os.path.join(BASE_DIR, 'templates')]
     64         ,
     65         'APP_DIRS': True,
     66         'OPTIONS': {
     67             'context_processors': [
     68                 'django.template.context_processors.debug',
     69                 'django.template.context_processors.request',
     70                 'django.contrib.auth.context_processors.auth',
     71                 'django.contrib.messages.context_processors.messages',
     72             ],
     73         },
     74     },
     75 ]
     76 
     77 WSGI_APPLICATION = 'Shop.wsgi.application'
     78 
     79 
     80 # Database
     81 # https://docs.djangoproject.com/en/3.0/ref/settings/#databases
     82 
     83 DATABASES = {
     84     # 'default': {
     85     #     'ENGINE': 'django.db.backends.sqlite3',
     86     #     'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
     87     # }
     88     'default': {
     89         'ENGINE': 'django.db.backends.mysql',
     90         'NAME': 'shop',
     91         'USER': 'root',
     92         'PASSWORD': 'yxh1990',
     93         'HOST': '127.0.0.1',
     94         'OPTIONS': {'init_command': 'SET default_storage_engine=INNODB;'},
     95     }
     96 }
     97 
     98 
     99 # Password validation
    100 # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators
    101 
    102 AUTH_PASSWORD_VALIDATORS = [
    103     {
    104         'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    105     },
    106     {
    107         'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    108     },
    109     {
    110         'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    111     },
    112     {
    113         'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    114     },
    115 ]
    116 
    117 
    118 # Internationalization
    119 # https://docs.djangoproject.com/en/3.0/topics/i18n/
    120 
    121 LANGUAGE_CODE = 'en-us'
    122 
    123 TIME_ZONE = 'UTC'
    124 
    125 USE_I18N = True
    126 
    127 USE_L10N = True
    128 
    129 USE_TZ = True
    130 
    131 
    132 # Static files (CSS, JavaScript, Images)
    133 # https://docs.djangoproject.com/en/3.0/howto/static-files/
    134 
    135 STATIC_URL = '/static/'
    View Code

    2-3.Goods的Model设计

    Goods中的model主要包括:GoodsCategory(商品类别)、GoodsCategoryBrand(品牌名)、Goods(商品)、GoodsImage(商品轮播图)、Banner(轮播的商品)。

    修改Shop/apps/goods/models.py

      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 class GoodsCategory(models.Model):
      9     """
     10     商品类别
     11     """
     12     CATEGORY_TYPE = (
     13         (1, "一级类目"),
     14         (2, "二级类目"),
     15         (3, "三级类目"),
     16     )
     17     name = models.CharField(default="", max_length=30, verbose_name="类别名", help_text="类别名")
     18     code = models.CharField(default="", max_length=30, verbose_name="类别代码", help_text="类别代码")
     19     desc = models.CharField(default="", verbose_name="类别描述", help_text="类别描述")
     20     category_type = models.IntegerField(choices=CATEGORY_TYPE, verbose_name="类目级别", help_text="类目级别")
     21     parent_category = models.ForeignKey("self", null=True, blank=True, verbose_name="父类别", help_text="父目录",
     22                                         related_name="sub_cat")
     23     is_tab = models.BooleanField(default=False, verbose_name="是否导航", help_text="是否导航")
     24     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
     25 
     26     class Meta:
     27         verbose_name = "商品类别"
     28         verbose_name_plural = verbose_name
     29 
     30     def __str__(self):
     31         return self.name
     32 
     33 
     34 class GoodsCategoryBrand(models.Model):
     35     """
     36     品牌名
     37     """
     38     category = models.ForeignKey(GoodsCategory, related_name='brands', null=True, blank=True, verbose_name="商品类目")
     39     name = models.CharField(default="", max_length=30, verbose_name="品牌名", help_text="品牌名")
     40     desc = models.TextField(default="", max_length=200, verbose_name="品牌描述", help_text="品牌描述")
     41     image = models.ImageField(max_length=200, upload_to="brands/")
     42     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
     43 
     44     class Meta:
     45         verbose_name = "品牌"
     46         verbose_name_plural = verbose_name
     47         db_table = "goods_goodsbrand"
     48 
     49     def __str__(self):
     50         return self.name
     51 
     52 
     53 class Goods(models.Model):
     54     """
     55     商品
     56     """
     57     category = models.ForeignKey(GoodsCategory, verbose_name="商品类目")
     58     goods_sn = models.CharField(max_length=50, default="", verbose_name="商品唯一货号")
     59     name = models.CharField(max_length=100, verbose_name="商品名")
     60     click_num = models.IntegerField(default=0, verbose_name="点击数")
     61     sold_num = models.IntegerField(default=0, verbose_name="商品销售量")
     62     fav_num = models.IntegerField(default=0, verbose_name="收藏数")
     63     goods_num = models.IntegerField(default=0, verbose_name="库存数")
     64     market_price = models.FloatField(default=0, verbose_name="市场价格")
     65     shop_price = models.FloatField(default=0, verbose_name="本店价格")
     66     goods_brief = models.TextField(max_length=500, verbose_name="商品简短描述")
     67     goods_desc = UEditorField(verbose_name=u"内容", imagePath="goods/images/", width=1000, height=300,
     68                               filePath="goods/files/", default='')
     69     ship_free = models.BooleanField(default=True, verbose_name="是否承担运费")
     70     goods_front_image = models.ImageField(upload_to="goods/images/", null=True, blank=True, verbose_name="封面图")
     71     is_new = models.BooleanField(default=False, verbose_name="是否新品")
     72     is_hot = models.BooleanField(default=False, verbose_name="是否热销")
     73     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
     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     """
     87     goods = models.ForeignKey(Goods, verbose_name="商品", related_name="images")
     88     image = models.ImageField(upload_to="", verbose_name="图片", null=True, blank=True)
     89     image_url = models.CharField(max_length=300, null=True, blank=True, verbose_name="图片url")
     90     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
     91 
     92     class Meta:
     93         verbose_name = '商品图片'
     94         verbose_name_plural = verbose_name
     95 
     96     def __str__(self):
     97         return self.goods.name
     98 
     99 
    100 class Banner(models.Model):
    101     """
    102     轮播的商品
    103     """
    104     goods = models.ForeignKey(Goods, verbose_name="商品")
    105     image = models.ImageField(upload_to='banner', verbose_name="轮播图片")
    106     index = models.IntegerField(default=0, verbose_name="轮播顺序")
    107     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    108 
    109     class Meta:
    110         verbose_name = '轮播商品'
    111         verbose_name_plural = verbose_name
    112 
    113     def __str__(self):
    114         return self.goods.name
    goods/models.py

    其中引入了第三方富文本插件DjangoUeditor(from DjangoUeditor.models import UEditorField),将其放入Shop/extra_apps/目录下,并将其在Shop/Shop/settings.py文件中注册app(另外将其他的app也注册进去)

     1 INSTALLED_APPS = [
     2     'django.contrib.auth',
     3     'django.contrib.contenttypes',
     4     'django.contrib.sessions',
     5     'django.contrib.messages',
     6     'django.contrib.staticfiles',
     7     'apps.users.apps.UsersConfig',
     8     'DjangoUeditor',
     9     'users',
    10     'goods',
    11     'trade',
    12     'user_operation',
    13 ]
    Shop/Shop/settings.py

    2-4.Trades的Model设计

     Trade的model主要包括:ShoppingCart(购物车)、OrderInfo(订单)、OrderGoods(订单的商品详情)。

    修改Shop/apps/trade/models.py

     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 class ShoppingCart(models.Model):
    13     """
    14     购物车
    15     """
    16     user = models.ForeignKey(User, verbose_name="用户")
    17     goods = models.ForeignKey(Goods, verbose_name="商品")
    18     nums = models.IntegerField(default=0, verbose_name="购买数量")
    19 
    20     add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    21 
    22     class Meta:
    23         verbose_name = '购物车'
    24         verbose_name_plural = verbose_name
    25         unique_together = ("user", "goods")
    26 
    27     def __str__(self):
    28         return "%s(%d)".format(self.goods.name, self.nums)
    29 
    30 
    31 class OrderInfo(models.Model):
    32     """
    33     订单
    34     """
    35     ORDER_STATUS = (
    36         ("TRADE_SUCCESS", "成功"),
    37         ("TRADE_CLOSED", "超时关闭"),
    38         ("WAIT_BUYER_PAY", "交易创建"),
    39         ("TRADE_FINISHED", "交易结束"),
    40         ("paying", "待支付"),
    41     )
    42 
    43     user = models.ForeignKey(User, verbose_name="用户")
    44     order_sn = models.CharField(max_length=30, null=True, blank=True, unique=True, verbose_name="订单号")
    45     trade_no = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name=u"交易号")
    46     pay_status = models.CharField(choices=ORDER_STATUS, default="paying", max_length=30, verbose_name="订单状态")
    47     post_script = models.CharField(max_length=200, verbose_name="订单留言")
    48     order_mount = models.FloatField(default=0.0, verbose_name="订单金额")
    49     pay_time = models.DateTimeField(null=True, blank=True, verbose_name="支付时间")
    50 
    51     # 用户信息
    52     address = models.CharField(max_length=100, default="", verbose_name="收货地址")
    53     signer_name = models.CharField(max_length=20, default="", verbose_name="签收人")
    54     singer_mobile = models.CharField(max_length=11, verbose_name="联系电话")
    55 
    56     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    57 
    58     class Meta:
    59         verbose_name = u"订单"
    60         verbose_name_plural = verbose_name
    61 
    62     def __str__(self):
    63         return str(self.order_sn)
    64 
    65 
    66 class OrderGoods(models.Model):
    67     """
    68     订单的商品详情
    69     """
    70     order = models.ForeignKey(OrderInfo, verbose_name="订单信息", related_name="goods")
    71     goods = models.ForeignKey(Goods, verbose_name="商品")
    72     goods_num = models.IntegerField(default=0, verbose_name="商品数量")
    73 
    74     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    75 
    76     class Meta:
    77         verbose_name = "订单商品"
    78         verbose_name_plural = verbose_name
    79 
    80     def __str__(self):
    81         return str(self.order.order_sn)
    Shop/apps/trade/models.py

    2-5.user_operation的Model设计

    user_operation主要包括:UserFav(用户收藏)、UserLeavingMessage(用户留言)、UserAddress(用户收货地址)

    修改Shop/apps/user_operation/models.py

     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 # Create your models here.
    10 class UserFav(models.Model):
    11     """:
    12     用户收藏
    13     """
    14     user = models.ForeignKey(User, verbose_name="用户")
    15     goods = models.ForeignKey(Goods, verbose_name="商品")
    16     add_time = models.DateTimeField(default=datetime.now, verbose_name=u"添加时间")
    17 
    18     class Meta:
    19         verbose_name = '用户收藏'
    20         verbose_name_plural = verbose_name
    21 
    22     def __str__(self):
    23         return self.user.name
    24 
    25 class UserLeavingMessage(models.Model):
    26     """
    27     用户留言
    28     """
    29     MESSAGE_CHOICES = (
    30         (1, "留言"),
    31         (2, "投诉"),
    32         (3, "询问"),
    33         (4, "售后"),
    34         (5, "求购")
    35     )
    36     user = models.ForeignKey(User, verbose_name="用户")
    37     message_type = models.IntegerField(default=1, choices=MESSAGE_CHOICES, verbose_name="留言类型",
    38                                       help_text=u"留言类型: 1(留言),2(投诉),3(询问),4(售后),5(求购)")
    39     subject = models.CharField(max_length=100, default="", verbose_name="主题")
    40     message = models.TextField(default="", verbose_name="留言内容", help_text="留言内容")
    41     file = models.FileField(upload_to="message/images/", verbose_name="上传的文件", help_text="上传的文件")
    42     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    43 
    44     class Meta:
    45         verbose_name = "用户留言"
    46         verbose_name_plural = verbose_name
    47 
    48     def __str__(self):
    49         return self.subject
    50 
    51 class UserAddress(models.Model):
    52     """
    53     用户收货地址
    54     """
    55     user = models.ForeignKey(User, verbose_name="用户" )
    56     province = models.CharField(max_length=100, default="", verbose_name="省份")
    57     city = models.CharField(max_length=100, default="", verbose_name="城市")
    58     district = models.CharField(max_length=100, default="", verbose_name="区域")
    59     address = models.CharField(max_length=100, default="", verbose_name="详细地址")
    60     signer_name = models.CharField(max_length=100, default="", verbose_name="签收人")
    61     signer_mobile = models.CharField(max_length=11, default="", verbose_name="电话")
    62     add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")
    63 
    64     class Meta:
    65         verbose_name = "收货地址"
    66         verbose_name_plural = verbose_name
    67 
    68     def __str__(self):
    69         return self.address
    Shop/apps/user_operation/models.py

    2-6.migrations原理及表生成

    注意,生成表之前检查所有的app都已经在Shop中的settings.py文件中注册。

     运行makemigrations命令,提示错误:

     原因是settings.py中 INSTALLED_APPS配置了两次users,以下两种方式取其中一个即可:

     

     报错:“TypeError: __init__() missing 1 required positional argument: 'on_delete'”,因为django 升级到2.0之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常:

    参考链接:https://blog.csdn.net/KreaWu/article/details/89400647

    on_delete各个参数的含义如下:

    on_delete=None,           # 删除关联表中的数据时,当前表与其关联的field的行为
    on_delete=models.CASCADE,        # 删除关联数据,与之关联也删除
    on_delete=models.DO_NOTHING,    # 删除关联数据,什么也不做
    on_delete=models.PROTECT,      # 删除关联数据,引发错误ProtectedError
    # models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True)
    on_delete=models.SET_NULL,     # 删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空,一对一同理)
    # models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值')
    on_delete=models.SET_DEFAULT,   # 删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值,一对一同理)
    on_delete=models.SET,          # 删除关联数据,
      a. 与之关联的值设置为指定值,设置:models.SET(值)
      b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)

    修改错误直到成功:

     再次运行命令migrate命令生成所有app对应的表,或者migrate appname命令,生成对应appname的表

     生成的数据库表:

    如果修改model后,需要重新原型命令makemigrations,然后再执行命令migrate。

    引入xadmin,期间运行Tools-Run manage.py Task遇到错误,是由于xadmin与django不兼容的情况,需修改相关文件,参考:

    https://github.com/sshwsfc/xadmin(xadmin的github网址)

    https://www.cnblogs.com/xingfuggz/p/10142388.html

    https://blog.csdn.net/huanglianggu/article/details/84328301

    直到没有报错为止,再次运行命令makemigrations和命令migrate。

    创建超级用户:

     1 manage.py@Shop > createsuperuser
     2 "D:Program FilesJetBrainsPyCharm 2018.1.4in
    unnerw.exe" E:PycharmProjectsEnvsVueShopScriptspython.exe "D:Program FilesJetBrainsPyCharm 2018.1.4helperspycharmdjango_manage.py" createsuperuser E:/PycharmProjects/Shop
     3 Tracking file by folder pattern:  migrations
     4 Username:  admin
     5 邮箱:  yuanxihui@163.com
     6 Warning: Password input may be echoed.
     7 Password:  admin123
     8 Warning: Password input may be echoed.
     9 Password (again):  admin123
    10 The password is too similar to the username.
    11 Bypass password validation and create user anyway? [y/N]: This password is too common.
    12  y
    13 Superuser created successfully.
    14 
    15 Process finished with exit code 0
    createsuperuser

     运行项目:

    1.遇到错误:TypeError: login() got an unexpected keyword argument 'extra_context'

    解决办法:https://blog.csdn.net/weixin_39418139/article/details/100554491

    2.遇到错误:'Media' object has no attribute 'add_css'

    解决方法:https://www.cnblogs.com/meticuloustodo/p/10368221.html

    3.遇到错误:AttributeError: 'CharField' object has no attribute 'rel'

    解决方法:https://blog.csdn.net/GoAheadNeverTurnBack/article/details/81433629

    4.遇到错误:TypeError: render() got an unexpected keyword argument 'renderer'

    解决方法:https://blog.csdn.net/xiaosongshine/article/details/88548348

    注释掉  renderer=self.form.renderer

    5.遇到错误:IndexError: list index out of range

    解决方法:https://blog.csdn.net/yuhan963/article/details/79167743

    源代码:

    input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('
    ') if ht != '']

    修改为:

    input_html = [ht for ht in super(AdminSplitDateTime, self).render(name, value, attrs).split('><') if ht != '']
    input_html[0] = input_html[0] + "/>"
    input_html[1] = "<" + input_html[1]

    注意原博客input_html中是以“/<>”分割input_html的,但是打印发现我的input_html中input标签没有/>,故修改split('/<>')为split('<>')

  • 相关阅读:
    基于Metaweblog API 接口一键发布到国内外主流博客平台
    uva144 Student Grants
    Uva 10452
    Uva 439 Knight Moves
    Uva 352 The Seasonal War
    switch语句
    java——基础知识
    我的lua学习2
    codeforces 431 D. Random Task 组合数学
    codeforces 285 D. Permutation Sum 状压 dfs打表
  • 原文地址:https://www.cnblogs.com/smartsmile-yxh/p/12655392.html
Copyright © 2011-2022 走看看