1 ORM 概述
当前项目的开发都是数据库驱动,即分析出项目中所需要存储的数据,然后设计数据表结构,接下来对通过编写 SQL 语句对数据库中的表进行 CURD 操作。
Django 提供了一套针对数据库操作的代码库, 通过该代码库中提供的工具, 我们可以创建查询、生成SQL语句,并且这些SQL无需开发人员自己处理。这样带来的好处是开发人员无需对 SQL 和 关系型数据库有深入的了解就能直接编写自己的查询。
我们把这套库称作 ORM 库, ORM 是对象关系映射, 对象表示的是我们Python中的对象概念, 关系指的是关系型数据库. 通过 ORM 完成 对象和 数据库中的表之前的一一对应关系. 对对象的任何操作就是对表的操作.
另外 ORM 强大的地方,ORM支持多种数据库后端。可非常简单帮助我们切换后端数据库。Django中提供了自己内置的 ORM 库。我们不需要面向数据库编程,而是通过定义模型类,通过对我们的模型类和对象的方法调用,从而完成了对数据库 CRUD 操作。
简言之, ORM 库帮我们封装了对关系型数据库的 CRUD 操作, 我们不需要编写一行 SQL, 即可完成对数据库的操作.
2 数据库配置
打开 ttsx/settings.py 文件, 在该配置文件中默认使用的是 SQLITE 数据库, 原 SQLITE 配置内容如下:
代码语言:javascript复制DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
现配置项目数据库为 MYSQL:
代码语言:javascript复制DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # mysql数据库引擎
'NAME': 'my_ttsx', # 数据库名字
'USER': 'root', # 用户名
'PASSWORD': 'chuanzhi', # 密码
'HOST': 'localhost', # 主机
'PORT': '3306' # 端口
}
}
配置完成之后, 在 ttsx 目录下的 __init__.py 中增加如下代码:
代码语言:javascript复制import pymysql
pymysql.install_as_MySQLdb()
一定要保证配置文件中指定的数据库是存在的, 如果不存在需要创建对应数据库. 启动测试服务器, 如果没有报错, 那么表示配置成功.
3 创建模型
在 Django 中一个模型类就对应着数据库中的一张表, 对模型类的任何操作都是对数据库表的操作. 在该项目中, 我们需要对业务进行分析, 然后创建所需要的表.
关于商品展示部分, 我们需要两张数据库表:
- GoodsCategory 表, 存储商品分类信息.
- 分类显示名称
- 分类显示样式
- 分类显示图片
- GoodsInfo 表, 存储商品具体信息.
- 商品名称
- 商品单位
- 商品价格
- 商品图片
- 商品描述
- 商品分类
关于购物车部分, 我们也需要两张表:
- OrderInfo 表, 存储订单基本信息.
- 订单编号
- 收货地址
- 收货人
- 联系电话
- 订单运费
- 订单备注
- 订单状态
- OrderGoods 表, 存储订单所对应的商品信息.
- 订单商品
- 商品数量
- 所属订单
针对我们分析的表结构, 我们创建对应的模型, 首先是创建商品展示相关的两个模型类, 在 goods 应用的 models.py 模块中编辑如下代码:
代码语言:javascript复制class GoodsCategory(models.Model):
"""商品分类模型"""
# 分类名称
cag_name = models.CharField(max_length=30)
# 分类样式
cag_css = models.CharField(max_length=20)
# 分类图片
cag_img = models.ImageField(upload_to='cag')
class GoodsInfo(models.Model):
"""商品信息模型"""
# 商品名字
goods_name = models.CharField(max_length=100)
# 商品单位
goods_unit = models.CharField(max_length=50)
# 商品价格
goods_price = models.IntegerField(default=0)
# 商品图片
goods_img = models.ImageField(upload_to='goods')
# 商品描述
goods_desc = models.CharField(max_length=2000)
# 所属分类
goods_cag = models.ForeignKey('GoodsCategory')
注意点:
- 模型类需要定义在 models.py 模块中.
- 模型类必须继承自 models.Model 类.
- 每一个类属性和数据库表中的一个字段一一对应.
类属性后面的字段类型是由 Django 定义, 方便将字段类型映射到不同的数据库中. 例如如下代码:
代码语言:javascript复制goods_name = models.CharField(max_length=100)
字段名叫做 goods_name, 字段的类型为 CharField, 对应到 MySQL 数据库的字段类型就为 varchar 类型, 并且长度为100. 除了 CharField, 我们还发现有其他不同的字段类型, 常用字段类型以及含义如下表所示:
使用时需要引入 django.db.models 包,字段类型如下:
字段类型 | 描述 |
---|---|
AutoField | 自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性. |
BooleanField | 布尔字段,值为True或False. |
NullBooleanField | 支持Null、True、False三种值. |
CharField(max_length=长度) | 字符串, 参数max_length表示最大字符个数.CharField必须指定max_length大小 |
TextField | 大文本字段 |
IntegerField | IntegerField 一个整数. 在Django所支持的所有数据库中,从 -2147483648 到 2147483647 范围内的值是合法的. |
DecimalField(max_digits=None, decimal_places=None) | 十进制浮点数.参数max_digits表示总位数.参数decimal_places表示小数位数. |
DateField[auto_now=False, auto_now_add=False]) | 日期. 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false.参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false.参数auto_now_add和auto_now是相互排斥的,组合将会发生错误. |
TimeField | 时间,参数同DateField |
DateTimeField | 日期时间,参数同DateField. |
FileField | 上传文件字段. |
ImageField | 继承于FileField,对上传的内容进行校验,确保是有效的图片. |
BigIntegerField | 一个64位整数, 类似于一个 IntegerField ,它的值的范围是 -9223372036854775808 到9223372036854775807之间. |
SmallIntegerField | 该字段值在 -32768 至 32767 |
表中并未解释 models.ForeignKey 字段的含义, 该字段主要用于建立外键, 表示表和表之间是一对多的关系, 例如, 商品分类和商品信息表之间就属于一对多的关系. 我们就可在商品信息模型中建立对商品分类的外键.
每个字段都会有一些字段选项:
选项类型 | 描述 |
---|---|
null | 如果为True,表示允许为空,默认值是False. |
db_column | 字段的名称,如果未指定,则使用属性的名称. |
db_index | 若值为True, 则在表中会为此字段创建索引,默认值是False. |
default | 默认值 |
primary_key | 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用. |
unique | 如果为True, 这个字段在表中必须有唯一值,默认值是False. |
- null.如果为True,Django 将会把数据库中空值保存为NULL。默认值是 False.
- blank. 如果为True,该字段允许为空值,默认为False。要注意,这与 null 不同。null纯粹是数据库范畴,指数据库中字段内容是否允许为空,而 blank 是表单数据输入验证范畴的。如果一个字段的blank=True,表单的验证将允许输入一个空值。如果字段的blank=False,该字段就是必填的。
- primary_key.如果为True,那么这个字段就是模型的主键。如果你没有指定任何一个字段的primary_key=True,Django 就会自动添加一个IntegerField 字段做为主键,所以除非你想覆盖默认的主键行为,否则没必要设置任何一个字段的primary_key=True。主键字段是只读的。如果你在一个已存在的对象上面更改主键的值并且保存,一个新的对象将会在原有对象之外创建出来。
下面我们在 cart 应用的 models.py 模块中创建购物车相关的模型类, 代码如下:
代码语言:javascript复制class OrderInfo(models.Model):
"""订单信息模型"""
status = (
(1, '待付款'),
(2, '待发货'),
(3, '待收货'),
(4, '已完成'),
)
# 订单编号
order_id = models.CharField(max_length=100)
# 收货地址
order_addr = models.CharField(max_length=100)
# 收货人
order_recv = models.CharField(max_length=50)
# 联系电话
order_tele = models.CharField(max_length=11)
# 运费
order_fee = models.IntegerField(default=10)
# 订单备注
order_extra = models.CharField(max_length=200)
# 订单状态
order_status = models.IntegerField(default=1, choices=status)
class OrderGoods(models.Model):
"""订单商品模型"""
# 所属商品
goods_info = models.ForeignKey('goods.GoodsInfo')
# 商品数量
goods_num = models.IntegerField()
# 商品所属订单
goods_order = models.ForeignKey('OrderInfo')
如下代码:
代码语言:javascript复制order_status = models.IntegerField(default=1, choices=status)
该代码中的 choices=status 表示的值为 status 指定的 4 个值中的一个.
我们所需要的模型创建好了, 下面就需要 Django 按照我们所定义的模型类来创建对应的数据库表. 首先我们先查看下项目目录结构, 会发现在 goods 应用和 cart 应用的 migrations 目录为空, 当我们执行迁移命令时, 对比该目录的变化:
图6
下面在终端执行迁移命令:
代码语言:javascript复制python manage.py makemigrations
命令执行效果如图7所示:
图7
下面我们再来看看 migrations 目录, 我们会发现多出名为 0001_initial.py 文件.
图8
0001_initial.py 文件我们可以理解为 SQL 的配置文件, 我们可将其转换为 SQL语句, 执行如下命令:
代码语言:javascript复制python manage.py sqlmigrate goods 0001
表示将 goods 应用下的 0001 配置文件转换为 SQL语句, 效果如图9所示:
图9
下面我们执行迁移命令, 执行对应的 SQL 语句, 在数据库中创建对应的数据库表, 执行迁移的命令如下:
代码语言:javascript复制python manage.py migrate
执行效果如图10所示:
图10
查看数据库, 我们已发现对应的数据库表已经创建, 但是表明并不是我们和我们模型类类名一直, 数据库中的表的格式为: 应用名字_模型类类名小写.
图11
对应模型的4张表名字分别为: cart_ordergoods、cart_orderinfo、goods_goodscategory、goods_goodsinfo.