拆分功能模块,创建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
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/‘
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
其中引入了第三方富文本插件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 ]
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)
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
注意,生成表之前检查所有的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 Files\JetBrains\PyCharm 2018.1.4\bin\runnerw.exe" E:\PycharmProjects\Envs\VueShop\Scripts\python.exe "D:\Program Files\JetBrains\PyCharm 2018.1.4\helpers\pycharm\django_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
运行项目:
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(‘\n‘) 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(‘<>‘)
Vue+Django REST framework 打造生鲜电商项目(学习笔记二)
原文:https://www.cnblogs.com/smartsmile-yxh/p/12655392.html