目录
一、ORM框架介绍
二、Django配置数据库
2.1 在本地mysql中创建数据库与用户
2.2 django 连接本地mysql(安装mysqlclient及依赖环境)mac安装
三、模型类
3.1、创建模型类&生成迁移脚本&执行迁移脚本
3.2 类属性&表字段介绍
3.2.1 models.CharField() 字符串
3.2.2 时间相关:DateTimeField 与DateField
3.2.3 自定义主键 primary_key=True
3.2.4 自定义表名称&内部类&排序
3.2.5 演示
四、CURD 增删改查
4.1 新增数据 Create
4.2 查询 Read
4.2.1 读取表里所有数据
4.2.2 读取单条数据 (不推荐): 模型类.objects.get(条件1=值1)
4.2.3 读取多/单条数据(推荐):objects.filter(条件1=值1)
4.2.4 .objects.filter 多种查询类型
4.2.5 .objects.exclude 反向查询 (常用)
五、QuerySet 介绍
六、公共模型类
下一章:
一、ORM框架介绍
ORM框架,把类和数据进行映射,通过类和对象操作它对应表格中的数据,进行增删改查(CRUD)
ORM框架中
数据库:需要提前手动创建数据库
数据表:与OMR框架中的模型类对应
字段:模型类中的类属性(Field子类)
记录:一行数据,多个模型类(字段)的实例。
二、Django配置数据库
2.1 在本地mysql中创建数据库与用户
1、启动本地的mysql
(我的是mac电脑,在系统偏好设置里,点击mysql图标进行启动)
root
123456
2.2 django 连接本地mysql(安装mysqlclient及依赖环境)mac安装
听说win安装mysqlclient 难度挺大,我这里用的mac
1、检查本地是否安装brew。如已经安装,跳过这一步
如果没有安装,则安装brew。安装brew的方法
/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"
安装brew方法:
mac 安装 brew 亲测有效_做测试的喵酱的博客-CSDN博客
2、安装mysql-client
我mac本地,安装的mysql 版本是5.7.10
所以我安装mysql-client 版本也要求为5.7
如果你是【mac】需要安装mysql-client (指定版本)
brew install mysql-client@5.7
如果你是 【Debian / Ubuntu】
sudo apt-get install python-dev default-libmysqlclient-dev
如果你是 【Red Hat / CentOS】
sudo yum install python-devel mysql-devel
3、【mac】配置mysql-client的环境变量
找到mysql-client的安装路径,一般为/opt/homebrew/Cellar/mysql-client@5.7/
配置环境变量
vim ~/.zshrc
export PATH="/opt/homebrew/opt/mysql-client@5.7/bin:$PATH"
使环境变量生效:
source ~/.zshrc
4、本地安装 mysqlclient
pip install mysqlclient
报错处理:
mac 安装 pip install mysqlclient 报错_做测试的喵酱的博客-CSDN博客
5、在数据库中,需要先手动创建一个库
CREATE DATABASE my_django charset=utf8mb4;
6、在settings.py 文件中,DATABASES 配置数据库信息
DATABASES = {
'default': {
# mysql数据库的引擎
'ENGINE': 'django.db.backends.mysql',
# 数据库的名称,需要连接mysql下具体某一个数据库的名称
'NAME': 'my_django',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
三、模型类
1、一般模型类都创建在models.py文件下
2、一个模型类,对应一张表
3、一个类属性,对应表里的一个字段
4、创建表时,会默认创建一个自增主键
类属性与表字段对应关系
类属性 | 表字段 |
CharField | varchar |
IntegerField | int |
BooleanField | bool |
TextField | 长文本 |
第一步:创建一个模型类
第二步:生成迁移脚本
第三步:执行迁移脚本
3.1、创建模型类&生成迁移脚本&执行迁移脚本
我们以前创建表的时候,是通过sql创建,如
CREATE TABLE table_name 。。。。
现在我们不通过sql,而是通过模型类创建表。
将一个模型类,转换成表。
1、创建一个模型类
类属性,对应数据库表中的字段。
一般模型类都创建在models.py文件下
models.py
from django.db import models
# Create your models here.
class Animal(models.Model):
# 数据库中varchar类型: 可变字符串,与CharField 对应
name = models.CharField(max_length=50)
# 数据库中int类型:与IntegerField 对应
age = models.IntegerField()
# bool 类型与 BooleanField 对应
gender = models.BooleanField()
2、生成迁移脚本
格式:
python manage.py makemigrations 子应用名称
如果不加子应用名称,则对所有的应用都生成迁移脚本
python manage.py makemigrations
如果只想迁移某一个子应用的数据,要指定子应用名称
举例:
在pycharm 中的 Terminal下执行
python manage.py makemigrations orders
在orders/migrations/0001_initial.py 生成了迁移脚本
3、执行迁移脚本
模版:
python manage.py migrate 子应用名称
如果后面不加子应用的名称,则会执行所有应用的迁移脚本。
举例:
我只执行oders应用下的迁移脚本
python manage.py migrate orders
执行完成后,可以去数据库中,看到新增的这个表。
生成的表名为 应用名称_小写的类名
4、扩展:将迁移脚本转成sql语句。
模版:
python manage.py sqlmigrate 应用名称 脚本名称
脚本名称,不需要以.py结尾
举例:
将orders下的 0001_initial.py 脚本,转成sql
python manage.py sqlmigrate orders 0001_initial
3.2 类属性&表字段介绍
属性 | 介绍 |
verbose_name=''字段的描述“ | '字段的描述“,好习惯会加verbose_name |
help_text='''字段的描述“ | '字段的描述“,好习惯会加help_text |
blank=True | 允许输入字段为空 |
null=True | 允许输入null |
default=xx | 设置字段的默认值为xx |
unique=True | 设置字段属性唯一 |
3.2.1 models.CharField() 字符串
1、models.CharField() 必须设置max_length=20
3.2.2 时间相关:DateTimeField 与DateField
DateTimeField 与DateField 特有的属性。
auto_now_add=True | 记录创建这条数据时的时间 |
auto_now=True | 记录这条数据更新时的时间 |
举例:
一条用户的信息数据,有一个创建时间create_time,和数据更新时间 update_time
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间', help_text='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间', help_text='更新时间')
3.2.3 自定义主键 primary_key=True
1、自定义主键 primary_key=True
ids = models.IntegerField(primary_key=True, verbose_name='商品id', help_text='商品id')
在一个模型类中,如果我们没有自定义主键,系统会自动创建一个主键id 。
2、设置自增主键 models.AutoField
id = models.AutoField(primary_key=True, verbose_name='商品id', help_text='商品id')
3.2.4 自定义表名称&内部类&排序
1、表的名称,默认为 应用名称_小写的类名。
我们想自定义表的名称,通过内部类实现.。
内部类 class Meta:
db_table 是固定写法。
2、表的描述
verbose_name = "商品表"
verbose_name_plural = "商品表"
class Goods(models.Model):
ids = models.IntegerField(primary_key=True, verbose_name='商品id', help_text='商品id')
# a.CharField类型必须指定max_length参数(改字段的最大字节数)
# b.如果需要给一个字段添加唯一约束,unique=True(默认为False)
name = models.CharField(max_length=20, verbose_name='商品名称', help_text='商品名称',
# h.可以在任意一个模型类中创建Meta内部类,用于修改数据库的元数据信息
class Meta:
# i.db_table指定创建的数据表名称
db_table = 'tb_goods'
# 为当前数据表,设置中午呢描述
verbose_name = "商品表"
verbose_name_plural = "商品表"
3.2.5 演示
1、models.py
from django.db import models
# Create your models here.
class Animal(models.Model):
# 数据库中varchar类型: 可变字符串,与CharField 对应
name = models.CharField(max_length=50)
# 数据库中int类型:与IntegerField 对应
age = models.IntegerField()
# bool 类型与 BooleanField 对应
gender = models.BooleanField()
class Goods(models.Model):
ids = models.IntegerField(primary_key=True, verbose_name='商品id', help_text='商品id')
# a.CharField类型必须指定max_length参数(改字段的最大字节数)
# b.如果需要给一个字段添加唯一约束,unique=True(默认为False)
name = models.CharField(max_length=20, verbose_name='商品名称', help_text='商品名称',
unique=True)
channel = models.CharField(max_length=10, verbose_name='商品渠道', help_text='商品渠道')
# c.使用default指定默认值(如果指定默认值后,在创建记录时,改字段传递,会使用默认值)
on_sale = models.BooleanField(verbose_name='是否在售', help_text='是否在售',
default=True)
# d.null=True指定前端创建数据时,可以指定该字段为null,默认为null=False,DRF进行反序列化器输入时才有效
# e.blank=True指定前端创建数据时,可以指定该字段为空字符串,默认为blank=False,DRF进行反序列化器输入时才有效
desc = models.TextField(verbose_name='商品描述', help_text='商品描述',
null=True, blank=True, default='')
# f.在DateTimeField、DateField等字段中,指定auto_now_add=True,在创建一条记录时,会自动将创建记录时的时间作为该字段的值,后续在更新数据时,就不再修改
# g.在DateTimeField、DateField等字段中,指定auto_now=True,在更新一条记录时,会自动将更新记录时的时间作为该字段的值
create_time = models.DateTimeField(auto_now_add=True, verbose_name='商品创建时间', help_text='商品创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='商品更新时间', help_text='商品更新时间')
# h.可以在任意一个模型类中创建Meta内部类,用于修改数据库的元数据信息
class Meta:
# i.db_table指定创建的数据表名称
db_table = 'tb_goods'
2、生成迁移脚本
python manage.py makemigrations orders
3、执行迁移脚本
python manage.py migrate orders
4、查看新生成的表
5、查看,将迁移脚本转成sql语句。
python manage.py sqlmigrate orders 0002_goods
四、CURD 增删改查
表中,一行数据(一条记录)就是一个模型类的实例对象。
商品goods的模型类如下:
class Goods(models.Model):
ids = models.IntegerField(primary_key=True, verbose_name='商品id', help_text='商品id')
# a.CharField类型必须指定max_length参数(改字段的最大字节数)
# b.如果需要给一个字段添加唯一约束,unique=True(默认为False)
name = models.CharField(max_length=20, verbose_name='商品名称', help_text='商品名称',
unique=True)
channel = models.CharField(max_length=10, verbose_name='商品渠道', help_text='商品渠道')
# c.使用default指定默认值(如果指定默认值后,在创建记录时,改字段传递,会使用默认值)
on_sale = models.BooleanField(verbose_name='是否在售', help_text='是否在售',
default=True)
4.1 新增数据 Create
在tb_goods表里,新增数据。实现方式,类的实例化
方式一: 模型类(字段名1=1值,字段名2=值2,....)
模版:
obj=Goods(ids="1",name="电脑",channel="电商")
obj.save()
两行代码,先实例化对象,再调用save方法。
注意:模型类的实例,必须调用save()方法,才会去执行sql
举例:
def get_good_1(request):
obj=Goods(ids="1",name="电脑",channel="电商")
obj.save()
return HttpResponse("传入一条数据")
配置url
path('get_good_1',views.get_good_1)
启动服务,调用接口:
http://127.0.0.1:8000/orders/get_good_1
表里新增了一条数据
方式二:模型类.objects.create(字段名1=1值,字段名2=值2,....)
模板:
Goods.objects.create(ids="2",name="鼠标",channel="线下")
举例:
def get_good_2(request):
Goods.objects.create(ids="2",name="鼠标",channel="线下")
return HttpResponse("创建第二条数据")
接口调用该方法,数据库成功新增一条数据
4.2 查询 Read
提前造一批数据,供查询演示
BEGIN;
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (1, '电脑', '电商', 1, '', '2023-05-16 09:26:00.350727', '2023-05-16 09:26:00.350855');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (2, '鼠标', '线下', 1, '', '2023-05-16 09:29:52.101118', '2023-05-16 09:29:52.101482');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (3, '插排', '电商', 1, '', '2023-05-16 09:40:30.336316', '2023-05-16 09:40:30.336393');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (4, '充电线', '线下', 1, '', '2023-05-16 09:40:32.963407', '2023-05-16 09:40:32.963456');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (5, '显示器', '电商', 1, '', '2023-05-16 09:41:10.128975', '2023-05-16 09:41:10.129023');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (6, '耳机', '线下', 1, '', '2023-05-16 09:41:07.905568', '2023-05-16 09:41:07.905732');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (7, '可乐', '电商', 1, '', '2023-05-16 09:41:44.799209', '2023-05-16 09:41:44.799275');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (8, '雪碧', '线下', 1, '', '2023-05-16 09:41:42.566164', '2023-05-16 09:41:42.566487');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (9, '笔记本', '电商', 1, '', '2023-05-16 09:42:17.367187', '2023-05-16 09:42:17.367240');
INSERT INTO `tb_goods` (`ids`, `name`, `channel`, `on_sale`, `desc`, `create_time`, `update_time`) VALUES (10, '主机', '线下', 1, '', '2023-05-16 09:42:15.143852', '2023-05-16 09:42:15.144253');
COMMIT;
4.2.1 读取表里所有数据
模板:
模型类.objects.all()
模型类.objects.all() 的返回结果,是将模型类对应的表,表里的所有数据都读出来。
注意,模型类.objects.all() 的返回结果是一个QuerySet对象(查询集对象)
QuerySet 查询集特性:
1、QuerySet对象,类似于列表,具有惰性查询的特性。在调用 模型类.objects.all()=QuerySet对象 时,是不会真正的去执行sql。 当具体去用数据时,才会执行sql语句。
举例:
查询集合
4.2.2 读取单条数据 (不推荐): 模型类.objects.get(条件1=值1)
方式一
模版:
qs = 模型类.objects.get(条件1=值1)
# 获取一行数据中,某个字段的值
变量名=qs.类属性名
举例:
tb_goods表中,ids="1"的数据
def get_read_2(request):
qs = Goods.objects.get(ids="1")
# 获取一行数据中,某个字段的值
name = qs.name
channel = qs.channel
注意:
1、 qs = Goods.objects.get(ids="1") 取出来的数据,qs 的type= <class 'orders.models.Goods'>
就是一个Goods的实例对象。 如果想获取具体某个字段的值,对象.属性名 就可以了
2、使用 模型类.objects.get(条件1=值1) 获取到的数据,必须只能是一条数据。
2.1如果返回结果是多条数据,会抛出异常。 比如查询
Goods.objects.get(name="电脑")
的数据,表里有多条name=电脑的数据,则使用objects.get 获取的数据大于1条,则会抛出异常。
2.2 如果查询条件,没有命中任何数据,也会抛出异常。 比如查询 ids="100"的数据,但是表里不存在ids="100"的数据,则也会抛出异常
所以在使用objects.get 的方法时,要注意try..catch..捕获异常
3、为了保证查询结果,只有一条数据符合条件,在使用条件查询时,最好使用具有唯一约束的条件去查询。比如id 之类的
4.2.3 读取多/单条数据(推荐):objects.filter(条件1=值1)
模版:
qs = 模型类.objects.filter(条件)
1、qs = Goods.objects.filter(ids="1")
返回结果,qs的类型是 QuerySet
2、查询结果无数据时,返回一个空的QuerySet对象
3、获取查询集QuerySet 中的第一条数据
Goods.objects.filter(ids="1")[0] 或者Goods.objects.filter(ids="1").frist()
4、获取查询集QuerySet 的长度
len(Goods.objects.filter(ids="1"))
或者
Goods.objects.filter(ids="1").count()
5、 QuerySet 支持for循环
举例:
def get_read_3(request):
qs = Goods.objects.filter(ids="1")
res=qs[0]
return HttpResponse(qs)
4.2.4 .objects.filter 多种查询类型
1、对字符串查询处理
模版:
字段名__查询类型=具体值
- 字段名__startswith:以xxx开头
- 字段名__istartswith:以xxx开头(忽略大小写)
- 字段名__endswith:以xxx结尾
- 字段名__isnull:是否为null
- 字段名__contains:包含
- 字段名__icontains:包含(忽略大小写)
- 在列表之内:字段名__in=[xx,xxx]
举例:
查询Student表中,姓名 name ,以姓“张”开头的学生
Students.objects.filter(name__startswith="张")
查询Student表中,姓名 name 中,包含“红” 的姓名信息
Students.objects.filter(name__contains="红")
Student表中,查询age 年龄 为 16岁 19 岁学生的信息
Students.objects.filter(age__in=[16,19])
2、对数字查询处理
模版:
字段名__查询类型=具体值
- 大于 gt (greate than) :字段名__gt
- 小于 lt (less than): 字段名__lt
- 等于 e (equal): 字段名__e
- 大于等于 :字段名__gte
举例:
Student表中,查询age 年龄大于等于18的学生信息
Students.objects.filter(age__gte=18)
4.2.5 .objects.exclude 反向查询 (常用)
objects.exclude 与 objects.filter 是相反的,但是查询类型是一模一样的。
举例:
查询Student表中,姓名 name ,查询 非姓“张”同学的信息
Students.objects.exclude(name__startswith="张")
查询Student表中,姓名 name 中,不包含“红” 的姓名的学生信息
Students.objects.exclude(name__contains="红")
五、QuerySet 介绍
# TODO
六、公共模型类
当我们有多个模型类,其中有很多重复字段时,我们可以把公共的字段提出来,封装成一个公共的类。
举例:
如 order_id 、order_name 两个字段,属于公共字段,很多模型类都会用到。将它封装成公共模型类
1、公共模型类
class BaseModel(models.Model):
order_id = models.CharField(max_length=10,verbose_name='订单id', help_text='订单id')
order_name = models.CharField(max_length=10,verbose_name='订单名称', help_text='名称')
class Meta:
# 在内部类Meta中,一旦指定abstract = True,那么当前模型类为抽象模型类,在迁移时不会创建表,仅仅是为了供其他类继承
abstract = True
注意:
内部类下,的 abstract=True 。在内部类Meta中,一旦指定abstract = True,那么当前模型类为抽象模型类,在迁移时不会创建表,仅仅是为了供其他类继承
2、继承
当需要用到这公共字段时,直接继承 公共内部类就可以了。
class Test(BaseModel):
下一章:
django ORM框架 第二章 表与表的关系&关联表_做测试的喵酱的博客-CSDN博客