随笔- 72  文章- 0  评论- 0  阅读- 6740 

正反向进阶操作

 # 正向查询
1.查询电话号码问1234的学校名称
    # res = models.School.objects.filter(schoolinfo_fo__phone='1234').values('name')
    # print(res)    # <QuerySet [{'name': '华清大学'}]>
2.查询学校名称为南芜大学的学生姓名及年龄
    # res = models.Student.objects.filter(school_fo__name='南芜大学').values('name', 'age')
    # print(res)     # <QuerySet [{'name': 'kevin', 'age': 20}]>
3.查询lili同学的老师姓名及年龄
    res = models.Teacher.objects.filter(student_fo__name='lili').values('name', 'age')
    print(res)    # <QuerySet [{'name': 'lili', 'age': 25}, {'name': 'jason', 'age': 28}]>

    # 反向查询
4.查询主键值为1的学校对应的学校信息 - -一对一
    # res = models.SchoolInfo.objects.filter(school__pk=1).values('phone', 'date_time')
    # print(res)      # <QuerySet [{'phone': '4321', 'date_time': datetime.date(2022, 9, 5)}]> 学校字段不加匹配不加括号
5.查询主键为1的学生对应的学校(学生 ---学校)--一对多
    # res = models.School.objects.filter(student__pk=1).values('name')
    # print(res)        # <QuerySet [{'name': '华清大学'}]>
 6.查询老师主键为1教授的学生姓名及年龄
    # res = models.Student.objects.filter(teacher__pk=1).values('name', 'age')
    # print(res)      # <QuerySet [{'name': 'lili', 'age': 18}, {'name': 'kevin', 'age': 20}]>

聚合查询

 1.通过聚合函数对数据进行查询(遵循正反向查询规律)关键字:aggregate

 from django.db.models import Max, Min, Count, Sum, Avg
1.查询学生年龄最小的学生姓名及年龄
    # age_info = models.Student.objects.aggregate(min_age=Min('age'))
    # print(age_info)  # {'min_age': 18}
2.查询学校数量
    # student_num = models.School.objects.aggregate(num=Count('name'))
    # print(student_num)   # {'num': 3}
3.查询lili同学的成绩平均值
    # result = models.Student.objects.filter(name='lili').aggregate(result_avg=Avg('result'))
    # print(result)   # {'result_avg': 62.8}
4.查询lili同学总共学习了几门课程
    # course = models.Student.objects.filter(name='lili').aggregate(course_sum=Sum('course'))
    print(course)     # {'course_sum': 3}

分组查询

 1.filter角色:在分组前使用相当于mysql中的where筛选 在分组后使用相当于mysql中的having过滤

 2.分组关键字:annotate

1.查询各学校中里面的学生人数
    # student_num = models.School.objects.annotate(student_num=Count('student__pk')).values('name', 'student_num')
    # print(student_num)   # <QuerySet [{'name': '南芜大学', 'student_num': 1}, {'name': '华清大学', 'student_num': 2}, {'name': '西南大学', 'student_num': 1}]>
2.统计学生学习的课程数量大于等于2门的学生姓名及课程数量
    course_num = models.Student.objects.annotate(course_num=Sum('course')).filter(course_num__gt=2).values('name', 'course_num')
    print(course_num)  # <QuerySet [{'name': 'kevin', 'course_num': 3}, {'name': 'tony', 'course_num': 4}]>

F查询

 1.F查询涉及查询字段都来源于表中字段非固定数据

 1.查询学生lili的地址前加中国
 from django.db.models import F, Value
 from django.db.models.functions import Concat
 models.Student.objects.filter(name='lili').update(addr=Concat(F('addr'), Value('中国')))

Q查询

 1.Q可以改变filter内多个条件之间的逻辑关系

1. 查询主键为1的学校及学生主键为1的学校
    # res = models.Student.objects.filter(Q(pk=1), Q(student__pk=1))  # ,and关系
    # res = models.Student.objects.filter(Q(pk=1) | Q(student__pk=1)) # |or关系
    # res = models.School.objects.filter(Q(pk=1) |~ Q(student__pk=1)) # ~not关系

 2.将查询条件字段改为字符串(用户输入)

    obj = Q()
    obj.connector = 'or'  # 默认是and的关系
    obj.children.append(('pk', 1))
    obj.children.append(('school_fo_id', 3))
    obj.children.append(('school_fo_id', 2))
    res = models.Student.objects.filter(obj)
    print(res)

ORM查询优化

1.减少数据库的查询(django orm默认是惰性查询 真正需要时才会执行代码)
2.django orm自带limit分页 减少数据库及服务端的压力
3.only与defer(会将括号内填写的字段封装成一个个数据对象)
  3.1 only:对象在点击括号中出现的字段 不会再走数据库查询
            对象点括号内没有的字段时 每次都会走数据库查询
          res = models.Student.objects.only('name', 'age')
          for obj in res:
              print(obj.name)
              print(obj.age)
              print(obj.addr)
              print(res.query)
  3.2 defer:数据对象点击括号中出现的字段 每次都会走数据库查询
             对象点击括号内不存在的字段 不会走数据库查询
        res = models.Student.objects.defer('name')
        for obj in res:
            print(obj.name)
            print(obj.age)
            print(obj.addr)
            print(res.query)
4.select_related与prefetch_related
  4.1 select_related:括号内只能接受外键字段(一对一 一对多)自动连表
      				 数据对象点击表中数据的时候不会走数据库查询
     res = models.Student.objects.all()
     for obj in res:
         print(obj.school_fo.name)
         print(res.query)     # 每次都会走数据库查询
       res = models.Student.objects.select_related('school_fo')  # 连表查询INNER JOIN
        for obj in res:
            print(obj.school_fo.name)
  4.2 prefetch_related:底层是子查询 将查询之后的结果一次性封装到数据对象中
      res = models.Student.objects.prefetch_related('school_fo')  # 子查询
      for obj in res:
          print(obj.school_fo.name)

事务操作

事务:ACID
事务隔离级别:脏读 幻读 不可重复读 ...
原生SQL: start transaction\rollback\commit\savepoint 

from django.db import transaction
try:
    with transaction.atomic():
        pass  # 多条ORM语句
except Exception as e:
        print(e)

ORM常见字段类型

 1.字段类型

字段类型 作用
AutoField() 主键自增
CharField() varchar(255)
IntegerField() 整数
BigIntegerField() 整数
DateField() 年月日
DateTimeField() 年月日 时分秒
DecimalField() 小数精确度最高
EmailField() 电子邮箱格式
BooleanField() 传布尔值返回数字0或1
TextField() 存储大段文本
FileField() 储存文件数据 自动指定存储位置 字段的具体路径
ForeignKey() 外键一对多
OneToOneField() 外键一对一
ManyToManyField() 外键多对多

 2.自定义字段类型

class MyCharField(models.Field):
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super().__init__(max_length=max_length, *args, **kwargs)

    def db_type(self, connection):
        return 'char(%s)' % self.max_length
info = MyCharField(max_length=32)

ORM常见参数

参数 作用
max_length 最大长度
verboses_name 起别名
auto_now 每次修改数据自动刷新时间
auto_now_add 第一次修改数据刷新时间
null
default 默认值
max_digits 最大个数
decimal_places 小数个数
unique=True 唯一
db_index=True 索引
choices 数据库中存放数字 节省空间 在models.py中进行数字与数据绑定
to 设置关联表
to_field 设置关联的字段
related_name 相关对象到此对象的关系的名称
on_delete models.CASCADE 级联删除(表中一条关联数据被删除 所有关联数据删除)
models.SET_NULL 当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null 定义外键时要写明允许为空
models.PROTECT 当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
models.SET_DEFAULT 当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
models.SET() 当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
models.DO_NOTHING 数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似

多对多创建方式

1.自动创建
  student_fo = models.ManyToManyField(to='Student')
  优点:第三张表自动创建
  缺点:第三张表扩展性差
2.手动创建
   	class Teacher(models.Model):
        pass
    class Student(models.Model):
        pass
 	class Teacher2Student(models.Model):
        student_id = models.ForeignKey(to="Teacher")
        teacher_id = models.ForeignKey(to="Student")
 	优点:第三张表扩展性强
  	缺点:无法使用正反向查询以及多对多四个方法
3.半自动创建
	class Teacher(models.Model):
        student_fo = models.ManyToManyField(to='Student',
                      through='Teacher2Student'
                      through_fields=('teacher_id','student_id')
                                        )
   	class Student(models.Model):
        pass
 	class Teacher2Student(models.Model):
        student_id = models.ForeignKey(to="Teacher")
        teacher_id = models.ForeignKey(to="Student")
   	优点:扩展性强并且支持正反向查询
  	 缺点:无法使用多对多四个方法
 posted on   拾荒菇凉  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示