什么是ORM
全称 Object Relational Mapping, 对象关系映射
类 --> 数据表
属性 --> 字段
对象 --> 数据行
使用ORM和sql连接数据库的区别
ORM
不用自己写sql语句 外键查询方便 执行效率不高(需要先将orm转化为sql)
sql语句
需要自己写sql 执行效率高
使用ORM
Django中连接数据库的配置
- settings.py
"""
数据库相关配置
"""
DATABASES = {
'default': {
# 使用sqlit3
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# 使用mysql
# 'ENGINE': 'django.db.backends.mysql',
# 'NAME': 'yky',
# 'HOST': '47.92.26.160',
# 'PORT': 3456,
# 'USER': 'root',
# 'PASSWORD': 'Byyhyy1234!',
}
}
- __init__.py
"""
将默认的mysqldb模块改为pymysql模块
使用pymysql模块连接数据库
"""
import pymysql
pymysql.install_as_MySQLdb()
操作数据表(表结构)
- models.py
"""
django会在person前添加"appName_"
创建appName_person表
"""
class Person(models.Model):
id = models.AutoField(primary_key=True) # 主键
name = models.CharField(max_length=32) # 最大长度32
age = models.IntegerField() # 最大长度为10
"""
unique = True # 唯一
null = True # 可以为空
blank = True # 允许django admin操作为空
"""
- 常用字段
# 字符串类型
CharField
# 自增类型
AutoField
# 时间类型
DateField
DateTimeField()
TimeField()
IntergeField()
- 常用参数
# 可以为空
null=True
# 默认值为0
default=0
# 唯一
unique=True
# 时间字段中,自动更新
auto_now_add=True 第一次创建时, 更新该字段
auto_add=True 每次数据被修改时, 更新该字段
- 执行命令
# 将变化都记录下来
python manage.py makemigrations
# 转换为sql语句执行
python manage.py migrate
操作数据内容
单表
增加
"""
向Person表中添加name为u1, age为16的数据
"""
models.Person.objects.create(name='u1', age=16)
删除
"""
删除name为u1的数据
"""
models.Person.objects.get(name='u1').delete()
修改
"""
先找到对应数据, 保存为对象
修改对象的属性
同步到数据库
"""
obj = models.Person.objects.get(name='u1')
obj.name = 'new_u1'
obj.save()
查询
普通方法
"""
1. 查询
"""
# 所有结果
models.Person.objects.all()
"""
2. 根据条件查询
"""
# 常用, 返回一个QuerySet列表
models.Person.objects.filter(id=2)
# 根据查询条件获取一个唯一的值, 不唯一或者无匹配都会报错, 慎用
models.Person.objects.get(id=2)
"""
3. 返回查询结果的多个字段
"""
# 返回一个QuerySet,里面是字典
models.Person.objects.filter(id=2).values('name','age')
# 返回一个QuerySet,里面是元祖
models.Person.objects.filter(id=2).values_list('name','age')
"""
4. 返回第一个或最后一个
"""
# 取第一个数据
models.Person.objects.filter(id=2).first()
# 取最后一个数据
models.Person.objects.filter(id=2).last()
"""
5. 对查询结果做处理
"""
# 将符合条件的都剔除掉,留下不符合条件的
models.Person.objects.filter(age=18).exclude(id=10)
# 对查询结果排序
models.Person.objects.filter(age=18).order_by('age')
# 对一个有序的查询结果集做反转
models.Person.objects.filter(age=18).reverse()
# 去重,跨表查询时去掉重复的记录,MySQL不支持按字段去重
models.Person.objects.filter(age=18).distinct()
"""
6. 返回查询信息
"""
# 返回数据条数
models.Person.objects.filter(age=18).count()
# 判断数据是否存在
models.Person.objects.filter(age=18).exists()
分类:
返回QuerySet列表
all(), filter(), exclude()
order_by(), reverse(), distinct()
values(), values_list()
返回具体对象
first(), last(), get()
返回数字
count()
返回布尔值
exists()
进阶方法 - 单表的双下划线
# id小于10, 大于1
models.Person.objects.filter(id__lt=10, id__gt=1)
# 获取id等于11、22、33的数据
models.Person.objects.filter(id__in=[11, 22, 33])
# not in
models.Person.objects.exclude(id__in=[11, 22, 33])
# 获取name字段包含"ven"的
models.Person.objects.filter(name__contains="ven")
# 不区分大小写
models.Person.objects.filter(name__icontains="ven")
# id范围是1到3的,类似于sql中的"bettwen 1 and 3"
models.Person.objects.filter(id__range=[1, 3])
# startwith, endwith
models.Person.objects.filter(name__startwith='张')
# date字段, birthday字段, 2018年的结果
models.Person.objects.filter(birthday__year=2018)
外键
一对多的关系, 通常外键建在"多"的一方
表结构
- models.py
"""
一个学校中有很多学生
所以外键在Person表建立
"""
class Person(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField(max_length=3)
# 级联删除, 2.0后需要手动指出, 1.11默认为此设置
school = models.ForeignKey(to="School", on_delete=models.CASCADE)
class School(models.Model):
name = models.CharField(max_length=32)```
外键查询
基于对象的正向查询
# 找到查询对象
person_obj = models.Person.objects.first()
# 对象.外键字段.查询字段
school_name = person_obj.school.name
基于QuerySet的正向查询(双下划线正向查询)
# 得到一个QuerySet
qs = models.Person.objects.all()
# 使用 "外键字段__查询字段"
ret = qs.values_list("school__name")
基于对象的反向查询
# 找到查询对象
school_obj = models.School.objects.get(id=2)
# 对象.查询表名_set
ret = school_obj.person_set.all()
基于QuerySet的反向查询(双下划线反向查询)
# 得到QuerySet
qs = models.School.objects.filter(id=1)
# 使用 "查询表__查询字段"
ret = qs.values_list("book__name")
多对多
一个人可以会很多种语言, 一种语言也有很多人会
"多对多的关系"
表结构
class Person(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField()
school = models.ForeignKey(to="School", on_delete=models.CASCADE)
language = models.ManyToManyField(to="Language", related_name='ooo')
class School(models.Model):
name = models.CharField(max_length=32)
class Language(models.Model):
name = models.CharField(max_length=32)
多对多查询
基于对象的正向查询
# 获取正向查询对象
person_obj = models.Person.objects.first()
# 对象.多对多的字段, 结果为QuerySet
data = person_obj.language
# 再使用values()/values_list()/all()处理QuerySet
ret = data.values_list('name')
ret = data.all()
基于QuerySet的正向查询
# 获取QuerySet
data = models.Person.objects.filter(id=1)
# 处理QuerySet, "查询表__查询字段"
ret = data.values('language__name')
基于对象的反向查询
# 获取反向查询对象
language_obj = models.Language.objects.last()
# 对象.表名_set, 结果为QuerySet
ret = language_obj.person_set
# 如果models中设置了related_name属性(related_name设定为ooo)
ret = language_obj.ooo
# 最后使用values()/values_list()/all()做处理
ret = data.values_list('name')
ret = data.all()
基于QuerySet的反向查询
# 获取QuerySet
data = models.Language.objects.filter(id=1)
# 处理QuerySet, "related_name__查询字段"
ret = data.values('ooo__name')
增加
当form表单提交的数据是列表(多选的select/多选的checkbox)时
使用request.POST.getlist("hobby")
# 参数是一个列表, 重新赋值
.set([i1, i2, i3])
# 参数是一个值, 添加新值
.add(i4)
"""
用户提交了
username = u1
language = ['英语','日语']
"""
# 先创建对象
user_obj = models.Person.objects.create(name=username)
# 设置对象
user_obj.language.set(language)