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_fo)     # 学校创建时间:2022-09-05  学校电话:4321
2.查询主键为1的学生对应的学校(学生 ---学校)--一对多
    # 先根据条件查询数据对象(学生对象)
    # student_obj = models.Student.objects.filter(pk=1).first()
    # 外键字段在学生表中 正向查询
    # print(student_obj.school_fo)     # 学校:华清大学
 3.查询主键为1的老师对应教授的学生(老师---学生)---多对多
    # 先根据条件查询数据对象(老师对象)
    # teacher_obj = models.Teacher.objects.filter(pk=1).first()
    # 外键字段在老师表中 正向查询
    # print(teacher_obj.student_fo.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_fo__phone': '1234'}]>


    # 2.查询主键为1的学生对应的学校名称及学生名字
    res = models.Student.objects.filter(pk=1).values('school__name', 'name')
    print(res)  # <QuerySet [{'school_fo__name': '华清大学', 'name': 'lili'}]>
    # 3.查询主键为2的老师对应的老师名字及学生姓名
    res = models.Teacher.objects.filter(pk=2).values('student__name', 'name')
    print(res)  # <QuerySet [{'student_fo__name': 'lili', 'name': 'jason'}, {'student__name': 'kevin', 'name': 'jason'}]>

    '''基于双下划线的反向跨表查询'''
    # 4.查询电话是5678的学校姓名
    res = models.SchoolInfo.objects.filter(phone='5678').values('school__name')
    print(res)     # <QuerySet [{'school__name': '西南大学'}]>
    # 5.查询学校为南芜大学的学生姓名及年龄
    res = models.School.objects.filter(name='南芜大学').values('student__name', 'student__age')
    print(res)    # <QuerySet [{'student__name': 'kevin', 'student__age': 20}]>

    # 6.查询学生lili教授的老师姓名和年龄
    res = models.Student.objects.filter(name='lili').values('teacher__name', 'teacher__age')
    print(res)    # <QuerySet [{'teacher__name': 'lili', 'teacher__age': 25}, {'teacher__name': 'jason', 'teacher__age': 28}]>

 posted on 2022-09-05 23:38  拾荒菇凉  阅读(118)  评论(0)    收藏  举报