数据模型的增删改查
一、 框架基本介绍
O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。
ORM
在Django
框架中的使用
django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。
-
使用
django
框架进行数据库开发的步骤- 配置数据库连接信息
- 在
models.py
中定义模型类 - 数据库迁移
- 通过操作类和对象完成对数据的增删改查操作
二、ORM
在Django
中的使用步骤
1-创建工程并修改配置参数
2-安装并注册应用 books
3-配置数据库连接信息
安装MySQL数据库驱动程序
python
pip install PyMySQL
在Django的工程同名子目录的__init__.py文件中添加如下语句,作用是让Django的ORM能以MySQLdb的方式来调用pyMySQL
python
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
在工程配置文件settings.py中修改DATABASES的配置信息
python
# django支持多数据库操作,在数据库迁移时默认使用 'default'数据库,想要在迁移时指定使用的数据库见【附2: ORM补充】
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 5000, # 数据库端口
'USER': 'django', # 数据库用户名
'PASSWORD': 'django', # 数据库用户密码
'NAME': 'django_demo' # 数据库名字
},
'bak': {
'ENGINE': 'django.db.backends.mysql',
'HOST': '127.0.0.1', # 数据库从机
'PORT': 5000, # 数据库端口
'USER': 'django', # 数据库用户名
'PASSWORD': 'django', # 数据库用户密码
'NAME': 'django_demo_bak' # 数据库名字
},
}
修改配置
python
DATABASES = {
"default": {
'ENGINE': 'dj_db_conn_pool.backends.mysql',
'HOST': '127.0.0.1', # 数据库主机
'PORT': 5000, # 数据库端口
'USER': 'django', # 数据库用户名
'PASSWORD': 'django', # 数据库用户密码
'NAME': 'django_demo' # 数据库名字
'POOL_OPTIONS': {
'POOL_SIZE': 10, # 最小
'MAX_OVERFLOW': 10, # 在最小的基础上,还可以增加10个,即:最大20个。
'RECYCLE': 24 * 60 * 60, # 连接可以被重复用多久(单位:秒),超过会重新创建,-1表示永久。
'TIMEOUT':30, # 池中没有连接最多等待的时间(单位:秒)。
}
}
}
在MySQL创建数据库
python
create database django_demo default charset=utf8;
使用root
账户为这个项目创建一个MySQL
管理员账户,管理项目相关的数据库
python
# 当前ubuntu虚拟机的mysql数据库root密码为:Root123
# 创建用户账号 django, 密码 django (由identified by 指明)
create user django identified by 'django';
# 授权django_demo数据库下的所有表(django_demo.*)的所有权限(all)给用户django在以任何ip访问数据库('django'@'%')
grant all on django_demo.* to 'django'@'%';
# 刷新生效用户权限
flush privileges;
4-在books
应用下的 models.py
文件中定义模型类
-
4.1 - 模型类定义规
-
模型类如果未指明表名,Django默认以 "小写app应用名_小写模型类名" 为数据库表名。可通过在模型类中嵌套定义一个类名为 "Meta" 的类, 并在Meta类中通过类属性 db_table 指明数据库表名.
-
数据库表名
- 关于主键 django会为表创建自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。 默认创建的主键列属性为id,可以使用pk(primary key)代替
-
4.2 - 属性命名限制
-
不能是python的保留关键字。
-
不允许使用连续的下划线,这是由
Django
的查询方式决定的。 -
定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下属性=models.字段类型(选项)
-
-
4.3 - 字段类型
类型 说明 AutoField
自动增长的 IntegerField
,通常不用指定,不指定时Django
会自动创建属性名为id的自动增长属性BooleanField
布尔字段,值为True或False NullBooleanField
支持Null、True、False三种值 CharField
字符串,参数max_length表示最大字符个数 TextField
大文本字段,一般超过4000个字符时使用 IntegerField
整数 DecimalField
十进制浮点数, 参数max_digits表示总位数, 参数decimal_places表示小数位数 FloatField
浮点数 DateField
日期, 参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为False; 参数auto_now_add和auto_now是相互排斥的,组合将会发生错误 TimeField
时间,参数同 DateField
DateTimeField
日期时间,参数同 DateField
FileField
上传文件字段 ImageField
继承于 FileField
,对上传的内容进行校验,确保是有效的图片 -
4.4 - 选项
选项 说明 verbose_name 用于设置该字段在Django管理后台中显示的人类可读的名称。通常用于提供更友好、可读性更强的字段名,以便开发者和管理员更容易理解字段的用途。 null 如果为True,表示允许为空,默认值是False blank 如果为True,则该字段允许为空白,默认值是False db_column 字段的名称,如果未指定,则使用属性的名称 db_index 若值为True, 则在表中会为此字段创建索引,默认值是False default 默认 primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为 AutoField
的选项使用unique 如果为True, 这个字段在表中必须有唯一值,默认值是False max_length 字符长度;必选项 auto_now_add 创建时,自动生成时间 auto_now 更新时,自动更新为当前时间 choices 一个用来选择值的2维元组。第一个值是实际存储的值,第二个用来方便进行选择。如SEX_CHOICES= (('F', 'Female'), ('M','Male'),) - null是数据库范畴的概念,blank是表单验证范畴的
-
4.5 - 外键
-
在设置外键时,需要通过on_delete选项指明主表删除数据时,对于外键引用表数据如何处理,在django.db.models中包含了可选常量:
-
CASCADE
级联,删除主表数据时连同一起删除外键表中数据 -
PROTECT
保护,通过抛出**ProtectedError
**异常,来阻止删除主表中被外键应用的数据 -
SET_NULL
设置为NULL,仅在该字段null=True允许为null时可用 -
SET_DEFAULT
设置为默认值,仅在该字段设置了默认值时可用 -
SET()
get_or_create作用 get_user_model作用 设置为特定值或者调用特定方法,如
-
python
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user),
)
5-以**【图书-英雄管理】** 为例进行 模型类定义与使用演示
-
创建应用
books
,在models.py
文件中定义模型类。pythonfrom django.db import models #定义图书模型类BookInfo class BookInfo(models.Model): btitle = models.CharField(max_length=20, verbose_name='名称') bpub_date = models.DateField(verbose_name='发布日期') bread = models.IntegerField(default=0, verbose_name='阅读量') bcomment = models.IntegerField(default=0, verbose_name='评论量') is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: # 指明数据库表名 db_table = 'tb_books' # 在admin站点中显示的名称 verbose_name = '图书' # 显示的复数名称 verbose_name_plural = verbose_name def __str__(self): """定义每个数据对象的显示信息""" return self.btitle #定义英雄模型类HeroInfo class HeroInfo(models.Model): GENDER_CHOICES = ( (0, 'male'), (1, 'female') ) hname = models.CharField(max_length=20, verbose_name='名称') hgender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别') hcomment = models.CharField(max_length=200, null=True, verbose_name='描述信息') hbook = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书') # 外键 is_delete = models.BooleanField(default=False, verbose_name='逻辑删除') class Meta: db_table = 'tb_heros' verbose_name = '英雄' verbose_name_plural = verbose_name def __str__(self): return self.hname
-
数据库迁移
-
数据库迁移说明
-
进行数据库迁移的目的是将模型类同步到数据库中。makemigrations 命令查找所有可用的模型,为任意一个在数据库中不存在对应数据表的模型创建迁移脚本文件。migrate 命令则运行这些迁移来自动创建数据库表。还提供可选的更丰富的控制模式。
-
生成迁移文件
pythonpython manage.py makemigrations
-
数据库迁移
pythonpython manage.py migrate # 指定连接的数据库,默认为default python manage.py migrate --database=default python manage.py migrate --database=bak # 指定迁移的应用 python manage.py migrate app01 --database=default 添加测试数据 添加图书数据 insert into tb_books(btitle,bpub_date,bread,bcomment,is_delete) values ('射雕英雄传','1980-5-1',12,34,0), ('天龙八部','1986-7-24',36,40,0), ('笑傲江湖','1995-12-24',20,80,0), ('雪山飞狐','1987-11-11',58,24,0); 添加英雄数据 insert into tb_heros(hname,hgender,hbook_id,hcomment,is_delete) values ('郭靖',1,1,'降龙十八掌',0), ('黄蓉',0,1,'打狗棍法',0), ('黄药师',1,1,'弹指神通',0), ('欧阳锋',1,1,'蛤蟆功',0), ('梅超风',0,1,'九阴白骨爪',0), ('乔峰',1,2,'降龙十八掌',0), ('段誉',1,2,'六脉神剑',0), ('虚竹',1,2,'天山六阳掌',0), ('王语嫣',0,2,'神仙姐姐',0), ('令狐冲',1,3,'独孤九剑',0), ('任盈盈',0,3,'弹琴',0), ('岳不群',1,3,'华山剑法',0), ('东方不败',0,3,'葵花宝典',0), ('胡斐',1,4,'胡家刀法',0), ('苗若兰',0,4,'黄衣',0), ('程灵素',0,4,'医术',0), ('袁紫衣',0,4,'六合拳',0);
-
-
6-通过类和对象完成数据增删改查操作
-
shell
工具的使用Django的manage工具提供了shell命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),以便可以直接在终端中执行测试python语句。
-
在终端(
Terminal
)中进入shell
交互环境pythonpython manage.py shell
-
导入两个模型类,以便后续使用
pythonfrom books.models import BookInfo, HeroInfo
-
-
查看
MySQL
数据库日志-
查看
mysql
数据库日志可以查看对数据库的操作记录。mysql
日志文件默认没有产生,需要做如下配置:pythonsudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
-
把68,69行前面的#去除,然后保存并使用如下命令重启
mysql
服务# 跳转到指定行: 在命令行模式下输入":行数"
sudo service mysql restart
-
使用如下命令打开
mysql
日志文件。# 实时查看数据库的日志内容
sudo tail -f /var/log/mysql/mysql.log
-
-
数据库 增、删、改、查
-
1 - 增加
-
使用说明
增加数据有两种方法。
方式一: 通过创建模型类对象,执行对象的save()方法保存到数据库中。
方式二: 通过模型类.objects.create()保存。
**可通过IDE自带的数据库插件连接数据库; 方便查看数据库数据变化、执行SQL语句
-
代码示例
python>>> from datetime import date >>> book = BookInfo( btitle='西游记', bpub_date=date(1988,1,1), bread=10, bcomment=10 ) >>> book.save() >>> hero = HeroInfo( hname='孙悟空', hgender=0, hbook=book ) >>> hero.save() >>> hero2 = HeroInfo( hname='猪八戒', hgender=0, hbook_id=book.id ) >>> hero2.save() >>> # 指定数据库: HeroInfo.objects.using("bak").create() >>> HeroInfo.objects.create( hname='沙悟净', hgender=0, hbook=book ) <HeroInfo: 沙悟净> >>> # 批量创建; batch_size 指定一次性提交的数量 >>> HeroInfo.objects.bulk_create( objs=[ HeroInfo(hname='红孩儿',hgender=0,hbook=book), HeroInfo(hname='铁扇公主',hgender=0,hbook=book) ], batch_size=3 ) [<HeroInfo: 红孩儿>, <HeroInfo: 铁扇公主>]
-
-
2 - 查询
-
2.1-基本查询
-
查询规则:
1. get 查询单一结果,如果不存在会抛出模型类 .DoesNotExist 异常,查询到多条数据会抛出MultipleObjectsReturned异常
2. all 查询多个结果。
3. count 查询结果数量。
4. values 与 values_list 查询指定字段的所有值
-
代码示例:
python>>> BookInfo.objects.all() <QuerySet [<BookInfo: 射雕英雄传>, <BookInfo: 天龙八部>, <BookInfo: 笑傲江湖>, <BookInfo: 雪山飞狐>, <BookInfo: 西游记>]> >>> book = BookInfo.objects.get(btitle='西游记') >>> book.id 5 >>> BookInfo.objects.all().values('btitle') >>> BookInfo.objects.all().values_list('btitle') >>> HeroInfo.objects.all().values('hbook_id').distinct() >>> BookInfo.objects.get(id=3) <BookInfo: 笑傲江湖> >>> BookInfo.objects.get(pk=3) <BookInfo: 笑傲江湖> >>> BookInfo.objects.get(id=100) """ Traceback (most recent call last): File "<console>", line 1, in <module> File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method return getattr(self.get_queryset(), name)(*args, **kwargs) File "/Users/delron/.virtualenv/dj/lib/python3.6/site-packages/django/db/models/query.py", line 380, in get self.model._meta.object_name db.models.DoesNotExist: BookInfo matching query does not exist. """
>>> BookInfo.objects.count()
-
-
2.2-过滤查询
-
查询规则
1. filter 过滤出多个结果
2. exclude 排除掉符合条件剩下的结果
3. get 过滤单一结果
-
过滤条件的使用语法
# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线
属性名称__比较运算符=值
-
代码演练
-
相等 exact:表示判等
# 查询编号为1的图书。
BookInfo.objects.filter(id__exact=1)
# 可简写为:
BookInfo.objects.filter(id=1)
-
模糊查询
-
使用语法
-
contains:是否包含(如果要包含 "%" 无需转义,直接写即可)
startswith、endswith:以指定值开头或结尾。
说明: 以下运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
-
代码示例
# 查询书名包含'传'的图书。
BookInfo.objects.filter(btitle__contains='传')
# 查询书名以'部'结尾的图书
BookInfo.objects.filter(btitle__endswith='部')
-
-
空查询
isnull
:是否为null。# 查询书名不为空的图书
BookInfo.objects.filter(btitle__isnull=False)
-
范围查询 in:是否包含在范围内
-
查询编号为1或3或5的图书
BookInfo.objects.filter(id__in=[1, 3, 5])
-
比较查询
-
使用语法gt 大于 (greater then)
-
gte 大于等于 (greater then equ)
lt 小于 (less then)
lte 小于等于 (less then equal)
exclude 不等于的运算符,使用exclude()过滤器
-
代码示例
-
查询编号大于3的图书
BookInfo.objects.filter(id__gt=3)
查询编号不等于3的图书
BookInfo.objects.exclude(id=3)
-
-
日期查询 year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。# 查询1980年发表的图书。BookInfo.objects.filter(bpub_date__year=1980)
查询1990年1月1日后发表的图书。BookInfo.objects.filter(bpub_date__gt=date(1990, 1, 1))
-
-
-
-