ORM操作数据准备及测试环境搭建
1.数据库切换:配置文件settings中配置mysql数据库
DATABASES = {
'default':{
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day59',
'HOST': '127.0.0.1',
'PORT': 3306,
'USER': 'root',
'PASSWORD': '123',
'CHARSET': 'utf8'
}
}
注:django1.X版本中切换数据库
import pymysql
pymysql.insstall_as_MySQLdb()
django2.X 3.X 4.X
pip install mysqlclient
2.定义模型类
2.1 在models.py文件中创建表字段
class Info(models.Model):
name = models.CharField(max_length(32), verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄')
now_time = models.Datefield(auto_now_add=True)
注:日期参数:
auto_now_add:只在创建数据的那一刻自动获取当前时间 之后不人为更改不变
auto_now:每次操作数据并保存都会自动跟新当前时间
3.执行数据库迁移命令(创表)
python manage.py makemigrations
python manage.py migrate
4.测试环境搭建:
4.1 在测试文件中或自行创建一个py文件
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'day59.settings')
# 前三行代码来源于django入门manage.py文件
import django
diango.setup()
import app01 import models # 导入顺序不能变 必须先创建环境才可以执行后续代码
res = models.Info.object.filter()
models.Info.object.create(name='lili', age='18')
print(res) # <QuerySet [<Info: Info object (1)>]> 结果为一个QuerySet对象
if __name__ == '__main__':
main()
4.2 pycharm提供测试环境:python console命令行测试环境
ORM关键字
1.关键字
1.pk:可以获取主键值(可忽略真正得主键字段名) 方便查询
2.__str__方法:对象打印时触发 便于后续对象数据查看及打印
3.QuerySet对象:
获得的是列表套对象 可通过for循环或者索引取值获取(索引不能以负数取值 并且没有该值会报错)
4.create:创建数据 返回值是当前创建的数据对象
save:通过类实例化产生对象 再通过save方法创建数据
5.update:更新数据
6.delete:删除数据
2.查询关键字
1.filter()
筛选数据 返回值为QuerySet(列表套数据对象)
注:括号内不写查询条件 默认查询所有
括号内可以填写条件 并且支持多个条件筛选 用逗号隔开 之间默认是and关系
2.all()
查询所有数据 返回值为QuerySet(列表套数据对象)
3.first()
获取QuerySet中的第一个数据对象 若无则返回None(数据对象)
4.last()
获取QuerSet中的最后一个数据对象 若无则返回None(数据对象)
5.get()
直接根据条件查询具体的数据对象 但条件不存在使报错(数据对象)
6.values()
指定查询字段 返回值为QuerySet(列表套字典)
注:括号中不写查询字段查询所有
括号里可以填写一个或多个字段 用逗号隔开 没有该字段会报错
7.values_list()
指定查询字段 返回值为QuerySet(列表套元组)
注:括号中不写查询字段查询所有
括号里可以填写一个或多个字段 用逗号隔开 没有该字段会报错
8.order_by()
指定字段排序 默认是升序 在字段前面加负号为降序 可以多字段排序 返回值为QuerySet(列表套数据对象)
注:降序必须选择字段 在字段前面加负号
9.count()
统计orm查询之后结果集中的数据个数
10.distinct()
针对重复的数据进行去重
注:字段数据必须一模一样才可以去重(主键字段不一致)
11.exclude()
针对括号内的条件取反查询数据 返回值为QuerySet(列表套数据对象)
注:不写条件查询全部 条件只能写一个 查询除该条件以外的数据 返回值为QuerySet(列表套数据对象)
12.reverse()
针对排序数据集做颠倒(不传参数) 返回值为QuerySet(列表套数据对象)
13.exists()
判断查询结果集是否有数据 返回布尔值(所有数据自带布尔值)
注:括号中不写条件
14.raw()
执行SQL语句 还可以借助模块
3.代码:
models.Info.objects.create(name='kevin', age=25)
models.Info.objects.filter(pk=2).update(name='jason')
res = models.Info.objects.filter()
models.Info.objects.filter(pk=2).delete()
res = models.Info.objects.filter()
res = models.Info.objects.all()
res = models.Info.objects.first()
res = models.Info.objects.last()
res = models.Info.objects.get(name='lili')
res = models.Info.objects.values()
res = models.Info.objects.values_list()
res = models.Info.objects.order_by('-name')
res = models.Info.objects.count()
res = models.Info.objects.distinct()
res = models.Info.objects.exclude(name='lili')
res = models.Info.objects.order_by('name').reverse()
res = models.Info.objects.exists()
print(res)
from django.db import connection
cursor = connection.cursor()
cursor.execute('insert into app01_info(name) VALUES ("jason")')
双下划线查询
1.比较运算符
字段__gt 大于 没有大于的该数据返回QuerySet空列表
字段__lt 小于
字段__gte 大于等于
字段__lte 小于等于
2.成员运算
字段__in
3.范围查询(数字)
字段__range
4.模糊查询
字段__contains 区分大小写
字段__icontains 不区分大小写
5.日期查询
字段__year
字段__month
字段__day
6.代码
res = models.Info.objects.filter(age__gt='18')
res = models.Info.objects.filter(age__lt='20')
res = models.Info.objects.filter(age__gte='20')
res = models.Info.objects.filter(age__lte='20')
res = models.Info.objects.filter(name__in=('jason',))
res = models.Info.objects.filter(age__range=(18, 22)) # 顾头顾尾
res = models.Info.objects.filter(name__contains='lili')
res = models.Info.objects.filter(name__icontains='lili')
res = models.Info.objects.filter(now_time__year=2022)
res = models.Info.objects.filter(now_time__month=6)
res = models.Info.objects.filter(now_time__day=5)
ORM底层SQL语句查看
1.方式一:
结果为QuerySet对象 直接点query查看SQL语句
2.方式二:
配置文件配置 打印所有的ORM操作对应的SQL语句
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
ORM多表查询
创建外键
1.对应关系:
一对一 ORM中外键字段建在查询次数多的一方
一对多 ORM中外键字段建在多的一方
多对多 ORM中创建多对多的外键方式有三种
方式一:直接在查询频率较高的表中填写字段即可 自动创建第三张表
方式二:自己创建第三张关系表
方式三:自己创建第三张关系表 但还要用orm对多对多字段做关联
2.创建外键语法:
一对一 models.OneToOneField() 会自动添加id后缀
一对多 models.ForeignKey() 会自动添加id后置
多对多 models.ManyToManyField()
注:django1.X针对models.ForeignKey() models.OneToOneField() 不需要on_delete参数
django2.X 3.X需要添加on_delete参数
外键字段数据操作
1.一对一:schoolinfo = models.OneToOneField(to='SchoolInfo', on_delete=models.CASCADE)
直接添加关联字段:models.School.objects.create(name='西南大学', schoolinfo_id=3)
通过间接使用外键虚拟字段添加数据对象:schoolinfo=schoolinfo_obj
1.一对多:school = models.ForeignKey(to='School', on_delete=models.CASCADE)
直接添加关联字段: models.Student.objects.create(name='tony', age=20, school_id=3)
通过间接使用外键虚拟字段添加数据对象:school=school_obj
2.多对多:student = models.ManyToManyField(to='Student')
add():添加数据 括号内即可以填写数字值也可以填写数据对象 支持多个
remove():删除数据 括号内即可以填写数字值也可以填写数据对象 支持多个
set():修改数据 括号内必须是可迭代对象
clear():清空指定数据 括号内不需要任何参数
正反向查询
1.正向查询:外键字段所在表查无外键字段所在表数据
eg:通过学生查学校 外键字段在学生表中
2.反向查询:无外键字段所在表数据查外键字段所在表
eg:通过学校查学生 外键字段不在学校字段中
注:ORM跨表查询口诀:正向查询按外键字段 反向查询按表名小写
基于对象查询(子查询)
1.查询主键值为1的学校对应的学校信息--一对一
# 先根据条件查询数据对象(学校对象)
# school_obj = models.School.objects.filter(pk=1).first()
# 外键字段在学校表中 正向查询
# print(school_obj.schoolinfo) # 学校创建时间:2022-09-05 学校电话:4321
2.查询主键为1的学生对应的学校(学生 ---学校)--一对多
# 先根据条件查询数据对象(学生对象)
# student_obj = models.Student.objects.filter(pk=1).first()
# 外键字段在学生表中 正向查询
# print(student_obj.school) # 学校:华清大学
3.查询主键为1的老师对应教授的学生(老师---学生)---多对多
# 先根据条件查询数据对象(老师对象)
# teacher_obj = models.Teacher.objects.filter(pk=1).first()
# 外键字段在老师表中 正向查询
# print(teacher_obj.student.all()) # <QuerySet [<Student: 学生:lili>, <Student: 学生:kevin>]>
4.查询电话号码为5678的学校名称(学校信息--学校)
# 先根据条件查询数据对象(学校信息对象)
# schoolinfo_obj = models.SchoolInfo.objects.filter(phone='5678').first()
# 外键字段在学校表中 反向查询
# print(schoolinfo_obj.school) # 学校:西南大学
5.查询学校名称为华清大学的学生姓名(反向查询)
# school_obj = models.School.objects.filter(name='华清大学').first()
# print(school_obj.student_set.all()) # <QuerySet [<Student: 学生:lili>, <Student: 学生:tom>]>
6.查询学生姓名为kevin的教授老师(反向查询)
student_obj = models.Student.objects.filter(name='kevin').first()
print(student_obj.teacher_set.all()) # <QuerySet [<Teacher: 老师:lili>, <Teacher: 老师:jason>]>
基于双下滑线查询
'''基于双下划线的正向跨表查询'''
1.查询华清大学的电话号码
res = models.School.objects.filter(name='华清大学').values('schoolinfo__phone')
print(res) # <QuerySet [{'schoolinfo__phone': '1234'}]>
2.查询主键为1的学生对应的学校名称及学生名字
res = models.Student.objects.filter(pk=1).values('school__name', 'name')
print(res) # <QuerySet [{'school__name': '华清大学', 'name': 'lili'}]>
3.查询主键为2的老师对应的老师名字及学生姓名
print(res) # <QuerySet [{'student__name': 'lili', 'name': 'jason'}, {'student__name': 'kevin', 'name': 'jason'}]>
'''基于双下划线的反向跨表查询'''
4.查询电话是5678的学校姓名
res = models.Schoolinfo.objects.filter(phone='5678').values('school__name')
print(res)
5.查询学校为南芜大学的学生姓名及年龄
res = models.School.objects.filter(name='南芜大学').values('student__name','student__age')
print(res)
6.查询学生lili教授的老师姓名和年龄
res = models.Student.objects.filter(name='lili').values('teacher__name','teacher__age')
print(res)
标签:__,Info,models,res,查询,objects,之字段,及表,django
From: https://www.cnblogs.com/040714zq/p/16660102.html