Django讲课笔记08:定义商城的数据模型
文章目录
- 零、本讲学习目标
- 一、课程导入
- (一)复习
- (二)ORM
- 二、新课讲授
- (一)commodity应用的模型定义
- (二)shopper应用的模型定义
- (三)模型定义说明
- 1、模型定义
- (1)定义模型字段
- (2)字段公共属性
- 2、重写__str__()
- 3、重写Meta选项
- (四)数据迁移创建数据表
- 1、使用终端命令生成数据迁移文件
- 2、使用终端命令进行数据迁移生成数据表
- 3、数据迁移小结
- (五)数据的导入与导出
- 1、准备测试数据
- 2、使用dumpdata导出数据
- (1)导出全部数据
- (2)导出某个应用的全部数据
- (3)导出应用里某个模型的全部数据
- (4)json数据文件乱码问题
- 3、使用loaddata命令导入数据
- 4、数据迁移编码问题小结
- 三、课堂小结
- 四、课后作业
- 五、拓展内容
零、本讲学习目标
- 掌握模型的定义
- 掌握创建数据表的命令
- 掌握数据迁移的命令
一、课程导入
(一)复习
- 视图
- 模板
- 路由
- 路由分发
(二)ORM
ORM (Object Relation Mapping) 框架是一种程序技术,用于实现面向对象编程语言中不同类型系统的数据之间的转换。从效果上说,它创建了一个可在编程语言中使用的“虚拟对象数据库”,通过对虚拟对象数据库的操作从而实现对目标数据库的操作,虚拟对象数据库与目标数据库是相互对应的。
二、新课讲授
在【Django讲课笔记05
】里,我们已设计了项目babies的数据结构,用户信息表是由Django内置用户管理功能定义,除此之外,项目还需要定义商品信息表
、商品类别表
、购物车信息表
和订单信息表
。我们将商品信息表
和商品类别表
定义在项目应用commodity
的models.py
;购物车信息表
和订单信息表
定义在项目应用shopper
的models.py
。
(一)commodity应用的模型定义
打开项目应用commodity的models.py文件,在文件中定义模型Types
和CommodityInfos
,它们以类的形式表示,并且继承父类Model
,详细的定义过程如下:
from django.db import modelsclass Types(models.Model):id = models.AutoField(primary_key=True)firsts = models.CharField('一级类型', max_length=100)seconds = models.CharField('二级类型', max_length=100)def __str__(self):return str(self.id)class Meta:verbose_name = '商品类型'verbose_name_plural = '商品类型'class CommodityInfos(models.Model):id = models.AutoField(primary_key=True)name = models.CharField('商品名称', max_length=100)sezes = models.CharField('颜色规格', max_length=100)types = models.CharField('商品类型', max_length=100)price = models.FloatField('商品价格')discount = models.FloatField('折后价格')stock = models.IntegerField('存货数量')sold = models.IntegerField('已售数量')likes = models.IntegerField('收藏数量')created = models.DateField('上架日期', auto_now_add=True)img = models.FileField('商品主图', upload_to=r'imgs')details = models.FileField('商品介绍', upload_to=r'details')def __str__(self):return str(self.id)class Meta:verbose_name = '商品信息'verbose_name_plural = '商品信息'
(二)shopper应用的模型定义
打开项目应用shopper的models.py文件,在文件中定义模型CartInfos
和OrderInfos
,模型的定义过程与模型Types
和CommodityInfos
相似,如下所示:
from django.db import modelsSTATE = (('待支付', '待支付'),('已支付', '已支付'),('发货中', '发货中'),('已签收', '已签收'),('退货中', '退货中'),
)class CartInfos(models.Model):id = models.AutoField(primary_key=True)quantity = models.IntegerField('购买数量')commodityInfos_id = models.IntegerField('商品ID')user_id = models.IntegerField('用户ID')def __str__(self):return str(self.id)class Meta:verbose_name = '购物车'verbose_name_plural = '购物车'class OrderInfos(models.Model):id = models.AutoField(primary_key=True)price = models.FloatField('订单总价')created = models.DateField('创建时间', auto_now_add=True)user_id = models.IntegerField('用户ID')state = models.CharField('订单状态', max_length=20, choices=STATE)def __str__(self):return str(self.id)class Meta:verbose_name = '订单信息'verbose_name_plural = '订单信息'
(三)模型定义说明
1、模型定义
(1)定义模型字段
每个模型字段对应数据表的某个表字段,字段以 aa= models.bb(cc) 格式表示,比如id = models.AutoField(primary_key=True),其中id为模型字段名称,它与数据表的表字段相互对应;models.AutoField是设置字段的数据类型,常用类型有整型、字符型或浮点型等;primary_key=True 是设置字段属性,例如字段是否为表主键
、限制内容长度
、设置默认值
等。
在实际开发中,我们需要定义不同的字段类型来满足各种开发需求,因此 Django 划分了多种字段类型,在源码目录 django\db\models\fields 的__init__.py 和 files.py 文件里找到各种模型字段,说明如下:
- AutoField:自增长类型,数据表的字段类型为整数,长度为 11 位。
- BigAutoField:自增长类型,数据表的字段类型为 bigint,长度为 20 位。
- CharField:字符类型。
- BooleanField:布尔类型。
- CommaSeparatedIntegerField:用逗号分隔的整数类型。
- DateField:日期(Date)类型。
- DateTimeField:日期时间(Datetime)类型。
- Decimal:十进制小数类型。
- EmailField:字符类型,存储邮箱格式的字符串。
- FloatField:浮点数类型,数据表的字段类型变成 Double 类型。
- IntegerField:整数类型,数据表的字段类型为 11 位的整数。
- BigIntegerField:长整数类型。
- IPAddressField:字符类型,存储 Ipv4 地址的字符串。
- GenericIPAddressField:字符类型,存储 Ipv4 和 Ipv6 地址的字符串。
- NullBooleanField:允许为空的布尔类型。
- PositiveIntegerFiel:正整数的整数类型。
- PositiveSmallIntegerField:小正整数类型,取值范围为 0~32767。
- SlugField:字符类型,包含字母、数字、下画线和连字符的字符串。
- SmallIntegerField:小整数类型,取值范围为-32,768~+32,767。
- TextField:长文本类型。
- TimeField:时间类型,显示时分秒 HH:MM[:ss[.uuuuuu]]。
- URLField:字符类型,存储路由格式的字符串。
- BinaryField:二进制数据类型。
- FileField:字符类型,存储文件路径的字符串。
- ImageField:字符类型,存储图片路径的字符串。
- FilePathField:字符类型,从特定的文件目录选择某个文件。
(2)字段公共属性
- verbose_name:默认为 None,在 Admin 站点管理设置字段的显示名称。
- primary_key:默认为 False,若为 True,则将字段设置成主键。
- max_length:默认为 None,设置字段的最大长度。
- unique:默认为 False,若为 True,则设置字段的唯一属性。
- blank:默认为 False,若为 True,则字段允许为空值,数据库将存储空字符串。
- null:默认为 False,若为 True,则字段允许为空值,数据库表现为 NULL。
- db_index:默认为 False,若为 True,则以此字段来创建数据库索引。
- default:默认为 NOT_PROVIDED 对象,设置字段的默认值。
- editable:默认为 True,允许字段可编辑,用于设置 Admin 的新增数据的字段。
- serialize:默认为 True,允许字段序列化,可将数据转化为 JSON 格式。
- unique_for_date:默认为 None,设置日期字段的唯一性。
- unique_for_month:默认为 None,设置日期字段月份的唯一性。
- unique_for_year:默认为 None,设置日期字段年份的唯一性。
- choices:默认为空列表,设置字段的可选值。
- help_text:默认为空字符串,用于设置表单的提示信息。
- db_column:默认为 None,设置数据表的列名称,若不设置,则将字段名作为数据表的列名。
- db_tablespace:默认为 None,如果字段已创建索引,那么数据库的表空间名称将作为该字段的索引名。注意:部分数据库不支持表空间。
- auto_created:默认为False,若为True,则自动创建字段,用于一对一的关系模型。
- validators:默认为空列表,设置字段内容的验证函数。
- error_messages:默认为 None,设置错误提示。
2、重写__str__()
重写函数__str__(),这是设置模型的返回值
,默认情况下,返回值为模型名+主键
。 函数__str__可用于外键查询,比如模型A设有外键字段F,外键字段F关联模型B,当查询模型A时,外键字段 F会将模型B的函数__str__返回值作为字段内容。 需要注意的是,函数__str__只允许返回字符类型
的字段,如果字段是整型或日期类型的,就必须使用 Python 的str()
函数将其转化成字符类型。
3、重写Meta选项
重写Meta选项,这是设置模型的常用属性,一共设有19
个属性,每个属性的说明如下:
- abstract:若设为 True,则该模型为抽象模型,不会在数据库里创建数据表。
- app_label:属性值为字符串,将模型设置为指定的项目应用,比如将index 的models.py定义的模型A指定到其他App里。
- db_table:属性值为字符串,设置模型所对应的数据表名称。
- db_tablespace:属性值为字符串,设置模型所使用数据库的表空间。
- get_latest_by:属性值为字符串或列表,设置模型数据的排序方式。
- managed:默认值为True,支持 Django 命令执行数据迁移;若为 False,则不支持数据迁移功能。
- order_with_respect_to:属性值为字符串,用于多对多的模型关系,指向某个关联模型的名称,并且模型名称必须为英文小写。比如模型A和模型B,模型A的一条数据对应模型B的多条数据,两个模型关联后,当查询模型 A的某条数据时,可使用 get_b_order()和 set_b_order()来获取模型 B 的关联数据,这两个方法名称的b为模型名称小写,此外get_next_in_order()和get_previous_in_order()可以获取当前数据的下一条和上一条的数据对象。
- ordering:属性值为列表,将模型数据以某个字段进行排序。
- permissions:属性值为元组,设置模型的访问权限,默认设置添加、删除和修改的权限。
- proxy:若设为 True,则为模型创建代理模型,即克隆一个与模型 A 相同的模型B。
- required_db_features : 属性值为列表, 声明模型依赖的数据库功能。比如 [‘gis_enabled’],表示模型依赖 GIS 功能。
- required_db_vendor:属性值为列表,声明模型支持的数据库,默认支持 SQLite、 PostgreSQL,MySQL 和 Oracle。
- select_on_save:数据新增修改算法,通常无须设置此属性,默认值为 False。
- indexes:属性值为列表,定义数据表的索引列表。
- unique_together:属性值为元组,多个字段的联合唯一,等于数据库的联合约束。
- verbose_name:属性值为字符串,设置模型直观可读的名称并以单数形式表示。
- verbose_name_plural:与 verbose_name 相同,以复数形式表示。
- label:只读属性,属性值为 app_label.object_name,如index的模型 PersonInfo,值为 index.PersonInfo。
- label_lower:与label相同,但其值为字母小写,如 index.personinfo。
(四)数据迁移创建数据表
数据迁移是将项目里定义的模型生成相应的数据表,首次在项目里定义模型时,项目所配置的数据库里并没有创建任何数据表,想要通过模型创建数据表,可使用 Django 的操作指令完成创建过程。以项目babies为例,在配置文件 settings.py 的 DATABASES 属性配置 MySQL 数据库连接信息,连接本地的 MySQL数据库系统。
1、使用终端命令生成数据迁移文件
- 执行命令:
python manage.py makemigrations
- 查看在两个应用中生成的数据迁移文件 -
0001_initial.py
- 查看
commodity/migrations/0001_initial.py
# Generated by Django 3.2.8 on 2021-11-09 02:13from django.db import migrations, modelsclass Migration(migrations.Migration):initial = Truedependencies = []operations = [migrations.CreateModel(name='CommodityInfos',fields=[('id', models.AutoField(primary_key=True, serialize=False)),('name', models.CharField(max_length=100, verbose_name='商品名称')),('sezes', models.CharField(max_length=100, verbose_name='颜色规格')),('types', models.CharField(max_length=100, verbose_name='商品类型')),('price', models.FloatField(verbose_name='商品价格')),('discount', models.FloatField(verbose_name='折后价格')),('stock', models.IntegerField(verbose_name='存货数量')),('sold', models.IntegerField(verbose_name='已售数量')),('likes', models.IntegerField(verbose_name='收藏数量')),('created', models.DateField(auto_now_add=True, verbose_name='上架日期')),('img', models.FileField(upload_to='imgs', verbose_name='商品主图')),('details', models.FileField(upload_to='details', verbose_name='商品介绍')),],options={'verbose_name': '商品信息','verbose_name_plural': '商品信息',},),migrations.CreateModel(name='Types',fields=[('id', models.AutoField(primary_key=True, serialize=False)),('firsts', models.CharField(max_length=100, verbose_name='一级类型')),('seconds', models.CharField(max_length=100, verbose_name='二级类型')),],options={'verbose_name': '商品类型','verbose_name_plural': '商品类型',},),]
- 查看
shopper\migrations\0001_initial.py
# Generated by Django 3.2.8 on 2021-11-09 02:13from django.db import migrations, modelsclass Migration(migrations.Migration):initial = Truedependencies = []operations = [migrations.CreateModel(name='CartInfos',fields=[('id', models.AutoField(primary_key=True, serialize=False)),('quantity', models.IntegerField(verbose_name='购买数量')),('commodityInfos_id', models.IntegerField(verbose_name='商品ID')),('user_id', models.IntegerField(verbose_name='用户ID')),],options={'verbose_name': '购物车','verbose_name_plural': '购物车',},),migrations.CreateModel(name='OrderInfos',fields=[('id', models.AutoField(primary_key=True, serialize=False)),('price', models.FloatField(verbose_name='订单总价')),('created', models.DateField(auto_now_add=True, verbose_name='创建时间')),('user_id', models.IntegerField(verbose_name='用户ID')),('state', models.CharField(choices=[('待支付', '待支付'), ('已支付', '已支付'), ('发货中', '发货中'), ('已签收', '已签收'), ('退货中', '退货中')], max_length=20, verbose_name='订单状态')),],options={'verbose_name': '订单信息','verbose_name_plural': '订单信息',},),]
- 暂时不处理警告信息(应该知道如何处理,就是那个斜杠放在总路由还是子路由的问题)
2、使用终端命令进行数据迁移生成数据表
- 0001_initial.py文件将models.py定义的模型生成数据表的脚本代码,该文件的脚本代码可被migrate指令执行,migrate指令会根据脚本代码的内容在数据库里创建相应的数据表,只要在PyCharm的Terminal窗口下输入migrate指令即可完成数据表的创建。
- 执行命令:
python manage.py migrate
- 在Navicat里打开babies数据库,查看刚才迁移生成的数据表
- 查看commodity_types表结构
- 查看commodity_commodityinfos表结构
- 查看shopper_cartinfos表结构
- 查看shopper_orderinfos表结构
3、数据迁移小结
makemigrations
和migrate
可以完成新建模型和生成数据表的作用,创建后,也可以修改模型后再次使用这两条命令,但新增加的字段只能将null和blank设置为True或者设置default也可以。- 另外,也可以单独执行指定的模型文件。如:migrate 指令还可以单独执行某个 .py 文件,首次在项目中使用 migrate 指令时,Django 会默认创建内置功能的数据表,如果只想执行项目应用 commodity 的 migrations 文件夹的某个 .py 文件,那么可以在 migrate 指令里指定文件名,指令如下:
python manage.py migrate commodity 0001_initial
(应该事先删除babies数据里的commodity_types表和commodity_commodityinfos表,还要删除django_migrations表里涉及到commodity的记录)
- 再执行一次这个命令,会提示“无迁移可应用”
在 migrate 指令末端设置项目应用名称 commodity 和 migrations 文件夹的0001_initial文件名,三者(migrate指令、项目应用名称 commodity 和 0001_initial 文件名)之间使用空格隔开即可,指令执行完成后,数据库只有数据表django_migrations、 commodity_types 和commodity_commodityinfos。
(五)数据的导入与导出
1、准备测试数据
- 在商品类型表里添加4条记录
2、使用dumpdata导出数据
(1)导出全部数据
- 在终端执行命令:
python manage.py dumpdata > data.json
- 查看导出全部数据的文件 - data.json
(2)导出某个应用的全部数据
- 在终端执行命令:
python manage.py dumpdata commodity > commodity_data.json
- 查看导出commodity应用的全部数据的文件 - commodity_data.json
(3)导出应用里某个模型的全部数据
- 在终端执行命令:
python manage.py dumpdata commodity.Types > commodity_types_data.json
(4)json数据文件乱码问题
- 用UTF8编码打开就会出现中文乱码
- 用GBK编码打开就能正常显示中文
3、使用loaddata命令导入数据
- 先清空commodity_types表里的记录
- 在终端执行命令:
python manage.py loaddata commodity_types_data.json
- 错误提示:由于json文件是GBK编码的,不能正常导入,必须将编码改成UTF8才能正常导入
- 再次导入数据,错误提示:采用UTF-8-BOM编码数据也不能导入
- BOM——Byte Order Mark,就是字节序标记
- 参看博文《UTF-8有BOM和无BOM的区别》
- 采用UTF-8编码保存数据文件
- 再次导入数据文件,成功导入
- 查看commodity_types表记录
4、数据迁移编码问题小结
- 使用Django的数据迁移可能会遇到许多问题,遇到问题时请查阅相关资料,也可以使用数据库的其他工具对数据进行迁移。
- PyCharm的编码设置
- 如何利用PyCharm将原本是GBK的json数据文件转换成不带BOM的UTF-8编码
- 注意:单击的是【Convert】按钮,而不是【Reload】按钮
三、课堂小结
- 重点掌握模型的定义
- 掌握命令makemigrations和migrate
- 掌握命令dumpdata和loaddata
四、课后作业
- 完成本讲模型定义并使用命令创建数据表
- 练习数据迁移命令
- 练习导入和导出数据
五、拓展内容
- Django数据迁移
https://code.ziqiangxuetang.com/django/django-data-migration.html - MySQL数据迁移
https://www.cnblogs.com/weibanggang/p/11568319.html
Django讲课笔记08:定义商城的数据模型相关推荐
- VB讲课笔记08:数组
VB讲课笔记08:数组 学习目标:理解数组的概念.掌握数组的声明.引用方法,掌握数组的使用以及与数组有关的常用算法:了解控件数组的概念.声明和使用. 一.数组概念 (一)数组定义 数组是高级程序设计语 ...
- Python+Django+Mysql实现购物商城推荐系统 基于用户、项目的协同过滤推荐购物商城系统 网络购物推荐系统 代码实现 源代码下载
Python+Django+Mysql实现购物商城推荐系统(基于用户.项目的协同过滤推荐算法) 一.项目简介 1.开发工具和实现技术 pycharm2020professional版本,python3 ...
- py218-基于Python+django的零食销售商城网站#毕业设计
开发语言:Python 编号:py218-基于Python+django的零食销售商城网站#毕业设计 python框架:django 软件版本:python3.7/python3.8 数据库:mysq ...
- py218-基于Python+django的鲜花销售商城网站#毕业设计
开发语言:Python 编号:py218-基于Python+django的鲜花销售商城网站#毕业设计 python框架:django 软件版本:python3.7/python3.8 数据库:mysq ...
- 基于Python+django的茶叶销售商城网站-计算机毕业设计
项目介绍 茶叶在我国历史悠久,这很多时候,人们在谈论事情的时候,都喜欢泡上一杯清茶这样不仅可以提神醒脑而且可以提升自己的品味.当前我国也有很多的爱茶人士.他们经常会购买自己所喜欢的茶叶在闲暇之时进行 ...
- 计算机毕业设计Python+django的零食销售商城网站(源码+系统+mysql数据库+Lw文档)
项目介绍 随着人们生活条件的改善,人们对生活的追求也越来越高.在闲暇之时品尝上美味的零食,是当前很多人的一个休闲方式.当前临时市场鱼目混杂,种类繁多很多消费者不知道如何去选购更加美味可口的零食.尤其 ...
- 基于Python+django的宠物销售商城网站-计算机毕业设计(源码+系统+mysql数据库+Lw文档)
项目介绍 宠物是人类最好的伙伴.尤其是近些年来,随着人们生活条件的改善,同时生活压力的增加越来越多的人.会选择宠物来相伴.在饲养宠物的同时,也会给这些铲屎官们带来一些困惑.例如,如何给这些宠物选择合适 ...
- py217-基于Python+django的服装销售商城网站#毕业设计
开发语言:Python 编号:py217-基于Python的服装销售商城网站 python框架:django 软件版本:python3.7/python3.8 数据库:mysql 5.7或更高版本 数 ...
- Django讲课笔记07:设置路由分发规则
文章目录 零.本讲学习目标 一.课程导入 (一)复习 (二)路由 二.新课讲授 (一)设置路由分发规则 1.创建应用的路由文件(子路由) - urls.py (1)创建index应用的路由文件 (2) ...
最新文章
- PostgreSQL 与 MySQL 相比,优势何在?[转]
- windows下编译lua源码
- websocket之二:WebSocket编程入门
- 高性能的索引实现——《深究MySQL》
- c++冒泡排序(附完整源码)
- mysql数据库备份方式,跳槽大厂必看!
- 2017.5.11 道路修建 思考记录
- 如何将Oracle中同一列的多行记录拼接成一个字符串 十一__262 | 浏览 8183 次 推荐于2016-01-25 17:34:18 最佳答案 需要用wm_concat函数来实现。
- Tableau可视化学习笔记:day07-08
- android 访问本地image url_微信图片无法通过 WXSS 获取,可使用网络图片或 base64或image...
- Rize - 一个可以让你简单、优雅地使用 puppeteer 的 Node.js 库
- 修改高通IPQ4019/4018的flash的分区
- html svg在线画板,很棒的SVG图形(多边形)在线生成器
- 怎样把excel中的图表插入PPT并且可以在PPT中编辑图表
- php 限制字数_PHP中如何正确统计中文字数
- 同期收治患者住院天数_合理用药监测指标
- 项目管理培训的一些总结
- 常用计算机控制芯片有哪些,电脑基本芯片的认识的常用知识介绍
- 计算广告(一):在线广告概述
- MinGW中的头文件路径