Python主流框架Django,ORM框架
数据模型的增删改查
一、 框架基本介绍
O是object,也就类对象的意思,R是relation,翻译成中文是关系,也就是关系数据库中数据表的意思,M是mapping,是映射的意思。在ORM框架中,它帮我们把类和数据表进行了一个映射,可以让我们通过类和类对象就能操作它所对应的表格中的数据。ORM框架还有一个功能,它可以根据我们设计的类自动帮我们生成数据库中的表格,省去了我们自己建表的过程。
ORM
在Django
框架中的使用
django中内嵌了ORM框架,不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据表的增删改查操作。
使用 django
框架进行数据库开发的步骤
models.py
中定义模型类 二、ORM
在Django
中的使用步骤
1-创建工程并修改配置参数
2-安装并注册应用books
3-配置数据库连接信息
安装MySQL数据库驱动程序
pip install PyMySQL
在Django的工程同名子目录的__init__.py文件中添加如下语句,作用是让Django的ORM能以MySQLdb的方式来调用pyMySQL
from pymysql import install_as_MySQLdb
install_as_MySQLdb()
在工程配置文件settings.py中修改DATABASES的配置信息
# 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' # 数据库名字
},
}
修改配置
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创建数据库
create database django_demo default charset=utf8;
使用root
账户为这个项目创建一个MySQL
管理员账户,管理项目相关的数据库
# 当前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'),) |
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作用 设置为特定值或者调用特定方法,如
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
文件中定义模型类。
from 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 命令则运行这些迁移来自动创建数据库表。还提供可选的更丰富的控制模式。
生成迁移文件
python manage.py makemigrations
数据库迁移
python 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
交互环境
python manage.py shell
导入两个模型类,以便后续使用
from books.models import BookInfo, HeroInfo
查看MySQL
数据库日志
查看mysql
数据库日志可以查看对数据库的操作记录。 mysql
日志文件默认没有产生,需要做如下配置:
sudo 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语句
代码示例
>>> 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 查询指定字段的所有值
代码示例:
>>> 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))
作者:D11_