01 搭建项目配置环境和创建表
先创建一个Django项目
在shop下的__init__中导入mysql
1
2
|
import pymysql
pymysql.install_as_MySQLdb() |
cmd命令框创建数据库
1
|
create database shop; |
配置mysql 读写分离配置
'default': { # 默认的配置的是主数据库 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': "123456", 'NAME': "shop" }, # 配置的是从数据库 'slave': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': "mysql", 'NAME': "shop" },
在项目的目录下新建utils/db_router.py文件:
在 utils/db_router.py中定义一个数据库路由,实现一个策略来控制特定模型的访问性
数据库路由
数据库路由是一个类,它提供4个方法:
数据库路由是一个类,它提供4个方法:
-
db_for_read(model, **hints)
-
建议model类型的对象的读操作应该使用的数据库。
如果一个数据库操作能够提供其它额外的信息可以帮助选择一个数据库,它将在hints字典中提供。合法的hints 的详细信息在下文给出。
如果没有建议,则返回None。
-
db_for_write(model, **hints)
-
建议Model 类型的对象的写操作应该使用的数据库。
如果一个数据库操作能够提供其它额外的信息可以帮助选择一个数据库,它将在hints字典中提供。 合法的hints 的详细信息在下文给出。
如果没有建议,则返回None。
-
allow_relation(obj1, obj2, **hints)
-
如果obj1 和obj2 之间应该允许关联则返回True,如果应该防止关联则返回False,如果路由无法判断则返回None。这是纯粹的验证操作,外键和多对多操作使用它来决定两个对象之间是否应该允许一个关联。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class MasterSlaveDBRouter( object ):
"""读写分离路由"""
def db_for_read( self , model, * * hints):
"""读数据库"""
return "slave"
def db_for_write( self , model, * * hints):
"""写数据库"""
return "default"
def allow_relation( self , obj1, obj2, * * hints):
"""是否运行关联操作"""
return True
|
在settings.py配置中声明读写分离路由所在的真正路径:
1
|
DATABASE_ROUTERS = [ "utils.db_router.MasterSlaveDBRouter" ]
|
为类补充字段
在utils目录中创建一个models.py用来'''为模型类补充字段'''的抽象类, 声明一个类是抽象类,不迁移,专门给别的表继承用的
在元选项中增添属性 abstract=True
from django.db import models class BaseModel(models.Model): '''为模型类补充字段''' create_time=models.DateTimeField(auto_now_add=True,verbose_name='创建时间') update_time=models.DateTimeField(auto_now=True,verbose_name='更新时间') class Meta: abstract=True # 声明是抽象模型类,不迁移,专门给别的表继承用的
创建应用
在项目队根目录下创建一个app目录用来存储所有的应用:(在app这个文件夹内,摁着Shift键再摁鼠标右键,打开命令框)
输入命令,分别创建 应用 cart goods orders users
在goods应用中的models中定义如下和商品相关的类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
from django.db import models
from utils.models import BaseModel
from tinymce.models import HTMLField
# Create your models here. class GoodsCategory(BaseModel):
"""商品类别表"""
name = models.CharField(max_length = 20 , verbose_name = "名称" )
logo = models.CharField(max_length = 100 , verbose_name = "标识" )
image = models.ImageField(upload_to = "category" , verbose_name = "图片" )
class Meta:
db_table = "df_goods_category"
verbose_name = "商品类别" # admin站点使用
verbose_name_plural = verbose_name
def __str__( self ):
return self .name
class Goods(BaseModel):
"""商品SPU表"""
name = models.CharField(max_length = 100 , verbose_name = "名称" )
# desc = HTMLField(verbose_name="详细介绍", default="", blank=True) 富文本编辑器
class Meta:
db_table = "df_goods"
verbose_name = "商品"
verbose_name_plural = verbose_name
def __str__( self ):
return self .name
class GoodsSKU(BaseModel):
"""商品SKU表"""
category = models.ForeignKey(GoodsCategory, verbose_name = "类别" )
goods = models.ForeignKey(Goods, verbose_name = "商品" )
name = models.CharField(max_length = 100 , verbose_name = "名称" )
title = models.CharField(max_length = 200 , verbose_name = "简介" )
unit = models.CharField(max_length = 10 , verbose_name = "销售单位" )
price = models.DecimalField(max_digits = 10 , decimal_places = 2 , verbose_name = "价格" )
stock = models.IntegerField(default = 0 , verbose_name = "库存" )
sales = models.IntegerField(default = 0 , verbose_name = "销量" )
default_image = models.ImageField(upload_to = "goods" , verbose_name = "图片" )
status = models.BooleanField(default = True , verbose_name = "是否上线" )
class Meta:
db_table = "df_goods_sku"
verbose_name = "商品SKU"
verbose_name_plural = verbose_name
def __str__( self ):
return self .name
class GoodsImage(BaseModel):
"""商品图片"""
sku = models.ForeignKey(GoodsSKU, verbose_name = "商品SKU" )
image = models.ImageField(upload_to = "goods" , verbose_name = "图片" )
class Meta:
db_table = "df_goods_image"
verbose_name = "商品图片"
verbose_name_plural = verbose_name
def __str__( self ):
return str ( self .sku)
class IndexGoodsBanner(BaseModel):
"""主页轮播商品展示"""
sku = models.ForeignKey(GoodsSKU, verbose_name = "商品SKU" )
image = models.ImageField(upload_to = "banner" , verbose_name = "图片" )
index = models.SmallIntegerField(default = 0 , verbose_name = "顺序" )
class Meta:
db_table = "df_index_goods"
verbose_name = "主页轮播商品"
verbose_name_plural = verbose_name
def __str__( self ):
return str ( self .sku)
class IndexCategoryGoodsBanner(BaseModel):
"""主页分类商品展示"""
DISPLAY_TYPE_CHOICES = (
( 0 , "标题" ),
( 1 , "图片" )
)
category = models.ForeignKey(GoodsCategory, verbose_name = "商品类别" )
sku = models.ForeignKey(GoodsSKU, verbose_name = "商品SKU" )
display_type = models.SmallIntegerField(choices = DISPLAY_TYPE_CHOICES, verbose_name = "展示类型" )
index = models.SmallIntegerField(default = 0 , verbose_name = "顺序" )
class Meta:
db_table = "df_index_category_goods"
verbose_name = "主页分类展示商品"
verbose_name_plural = verbose_name
def __str__( self ):
return str ( self .sku)
class IndexPromotionBanner(BaseModel):
"""主页促销活动展示"""
name = models.CharField(max_length = 50 , verbose_name = "活动名称" )
url = models.URLField(verbose_name = "活动连接" )
image = models.ImageField(upload_to = "banner" , verbose_name = "图片" )
index = models.SmallIntegerField(default = 0 , verbose_name = "顺序" )
class Meta:
db_table = "df_index_promotion"
verbose_name = "主页促销活动"
verbose_name_plural = verbose_name
def __str__( self ):
return self .name
|
在orders应用中的models中定义如下和订单相关的类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
from django.db import models
from utils.models import BaseModel
from app.users.models import User, Address
from app.goods.models import GoodsSKU
# Create your models here. class OrderInfo(BaseModel):
"""订单信息"""
PAY_METHOD_CHOICES = (
( 1 , "货到付款" ),
( 2 , "支付宝" ),
)
ORDER_STATUS_CHOICES = (
( 1 , "待支付" ),
( 2 , "待发货" ),
( 3 , "待收货" ),
( 4 , "待评价" ),
( 5 , "已完成" ),
)
order_id = models.CharField(max_length = 64 , primary_key = True , verbose_name = "订单号" )
user = models.ForeignKey(User, verbose_name = "下单用户" )
address = models.ForeignKey(Address, verbose_name = "收获地址" )
total_count = models.IntegerField(default = 1 , verbose_name = "商品总数" )
total_amount = models.DecimalField(max_digits = 10 , decimal_places = 2 , verbose_name = "商品总金额" )
trans_cost = models.DecimalField(max_digits = 10 , decimal_places = 2 , verbose_name = "运费" )
pay_method = models.SmallIntegerField(choices = PAY_METHOD_CHOICES, default = 1 , verbose_name = "支付方式" )
status = models.SmallIntegerField(choices = ORDER_STATUS_CHOICES, default = 1 , verbose_name = "订单状态" )
trade_id = models.CharField(max_length = 100 , unique = True , null = True , blank = True , verbose_name = "支付编号" )
class Meta:
db_table = "df_order_info"
class OrderGoods(BaseModel):
"""订单商品"""
order = models.ForeignKey(OrderInfo, verbose_name = "订单" )
sku = models.ForeignKey(GoodsSKU, verbose_name = "订单商品" )
count = models.IntegerField(default = 1 , verbose_name = "数量" )
price = models.DecimalField(max_digits = 10 , decimal_places = 2 , verbose_name = "单价" )
comment = models.TextField(default = " ", verbose_name=" 评价信息")
class Meta:
db_table = "df_order_goods"
|
在users应用中的models中定义如下和用户相关的类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
from django.db import models
from django.contrib.auth.models import AbstractUser
from utils.models import BaseModel
from django.conf import settings
from app.goods.models import GoodsSKU
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
# Create your models here. # django默认的认证机制,在setting installAPPs中的 'django.contrib.auth', # 所以我们要声明自己的认证路径 去setting配置,AUTH_USER_MODEL = "users.User" class User(AbstractUser, BaseModel):
"""用户"""
# 我们自己不用指明字段,django的默认字段,都通过继承AbstractUser它就有了
class Meta:
db_table = "df_users"
def generate_active_token( self ):
"""生成**令牌"""
serializer = Serializer(settings.SECRET_KEY, 3600 )
token = serializer.dumps({ "confirm" : self . id }) # 返回bytes类型
return token.decode()
class Address(BaseModel):
"""地址"""
user = models.ForeignKey(User, verbose_name = "所属用户" )
receiver_name = models.CharField(max_length = 20 , verbose_name = "收件人" )
receiver_mobile = models.CharField(max_length = 11 , verbose_name = "联系电话" )
detail_addr = models.CharField(max_length = 256 , verbose_name = "详细地址" )
zip_code = models.CharField(max_length = 6 , verbose_name = "邮政编码" )
class Meta:
db_table = "df_address"
|
用户认证模型类
在配置文件中,指定自己定义的认证系统使用的用户模型路径在user应用中的User类,django只支持模块和类名之间用.分隔,多了一个点就解析不出来,
如这样就解析不出来,AUTH_USER_MODEL = "app.users.User",所以要把它变成,users.User,所以将app目录添加到解析路径里
1
2
3
4
5
|
import sys
sys.path.insert( 1 , os.path.join(BASE_DIR, "app" ))
#认证系统使用的用户模型 AUTH_USER_MODEL = "users.User"
|
把注册的应用 添加到配置文件的INSTALLED_APPS中,因为上面在 自定义用户认证模型类的时候,已经把app目录添加到解析路径里了,所以不用app.users这样添加,直接写应用的名字:
执行迁移
1
2
3
|
python manage.py makemigrations python manage.py migrate |