文章目录
- ORM
- 简介
- 使用ORM
- Django中连接数据库的配置
- 操作数据表(表结构)
- 操作数据
- 增,删,改
- 查
- 根据结果分类
- 进阶方法 - 单表的双下划线
- 外键
- 表结构
- 外键查询
- 基于对象的正向查询
- 基于QuerySet的正向查询(双下划线正向查询)
- 基于对象的反向查询
- 基于QuerySet的反向查询(双下划线反向查询)
- 多对多
- 表结构
- 多对多查询
- 基于对象的正向查询
- 基于QuerySet的正向查询
- 基于对象的反向查询
- 基于QuerySet的反向查询
- 增加
ORM
简介
全称 Object Relational Mapping, 对象关系映射
类 --> 数据表
属性 --> 字段
对象 --> 数据行
使用ORM
Django中连接数据库的配置
- projectDir/__init__.py
"""
修改 django 连接 mysql 的模块为 pymysql
"""
import pymysql
pymysql.install_as_MySQLdb()
- 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': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': 'xxxxxx',
}
}
操作数据表(表结构)
- 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
"""
常用字段
-------
字符串类型 CharField
自增类型 AutoField
时间类型 DateField, DataTimeField, TimeField
最大长度为 10 的数字类型 IntergeField
常用参数
-------
数据可为空 null = True
admin 操作可留空 blank = True
默认值为 0 default = 0
数据唯一 unique = True
第一次创建时, 更新该字段 auto_now_add = True
每次数据被修改时, 更新该字段 auto_add=True
"""
- 命令行
# 需要在项目目录下执行
cd $projectDir
# 将变化都记录下来
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()
"""
改
先找到对应数据, 保存为对象, 修改对象的属性, 同步到数据库
将 name 从 u1 修改为 new_u1
"""
obj = models.Person.objects.get(name='u1')
obj.name = 'new_u1'
obj.save()
查
""" 1. 查询所有 """
# 常用语 list 展示
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)
外键
表结构
""" 一般是已知学生, 查学校, 所以外键在学生方创建 """
# vim models.py
class Person(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField(max_length=3)
school = models.ForeignKey(to="School", on_delete=models.CASCADE) # 级联删除, 2.0后需要手动指出, 1.11默认为此设置
class School(models.Model):
name = models.CharField(max_length=32)
外键查询
基于对象的正向查询
# 找到第一个学生
person_obj = models.Person.objects.first()
# 学生.school(外键字段).name(查询的外键字段)
school_name = person_obj.school.name
基于QuerySet的正向查询(双下划线正向查询)
# 得到一个QuerySet
qs = models.Person.objects.all()
# 使用 "外键字段__查询字段"
ret = qs.values_list("school__name")
基于对象的反向查询
# 找到id为2的学校
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)