表查询数据准备及测试环境搭建

sqllite3
django自带sqllite3小型数据库
该数据库功能非常有限,并且针对日期类型的数据兼容性很差
django切换MySQL数据
django1.x 版本的 需要在__init__文件导入模块
import pymysql
pymysql.install__as_MYSQLdb()

django2.x/3.x/4.x
 在终端下载 pip install mysqlclient
定义模型类
class Userinfo(models.Model):
    uid = models.AutoField(primary_key=True,verbose_name='编号')
    name = models.CharField(max_length=32,verbose_name='姓名')
    age = models.IntegerField(verbose_name='年龄')
    join_time = models.DateField(auto_now_add=True)

# DateField时间字段的两个重要参数
auto_time:每次操作数据的时候都会自动更新保存当前的时间
auto_time_add:只记录第一次创建的时间,之后不人为修改的话就一直是创建的时间
数据库迁移命令
终端输入命令:
 python manage.py makemigrations
 python manage.py migrate
模型测试环境准备
方式1: 在任意空的py文件中准备环境
import os
def main():
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject9_5.settings')  # 这两句直接在manage.py文件复制

    import django
    django.setup()

    from app01 import models
    print(models.Userinfo.objects.filter())

if __name__ == '__main__':
    main()

方式2:
pycharm提供测试环境
python console命令行测试环境

表查询关键字

常见查询关键字

创建数据

# create方法 
不止可以创建数据还可以返回当前创建的数据对象
可以使用对象点属性的方式获取值!

获取主键的两种方式:
 对象.主键名
 对象.pk    查找主键 不需要输入主键真正的名字 (适用于主键名较长或者不知道主键名的情况下)

django查询mysql范围查询 django orm查询指定字段_数据

创建数据的第二种方式:
 user_obj =models.Userinfo(name= 'jason',age=88) #创建数据
 user_obj.save()  # 保存数据

查询所有的数据:

# filter()  括号内不填写参数 默认查询所有 filter括号内的参数可以支持多个筛选条件,逗号隔开,默认是and关系
# all()  查询所有
返回值都是QuerySet(可以看成是列表套数据对象),可以用for循环取值,也可以索引取值,但是不支持负数索引!!!

django查询mysql范围查询 django orm查询指定字段_django查询mysql范围查询_02

# __str__方法 对象被打印(页面展示,数据查询) 的时候执行必须返回字符串类型的数据
直接返回对象名 更方便查看数据 推荐在models里面加上

django查询mysql范围查询 django orm查询指定字段_数据_03


django查询mysql范围查询 django orm查询指定字段_字段_04

查询第一个和最后一个

first()  查找数据的第一个数据 如果没有返回None 。
models.Userinfo.objects.filter().first()
也可以用索引 如果直接用索引,没有值的话会报错!推荐使用关键字
last()  查找数据的最后一个数据 如果没有返回None

django查询mysql范围查询 django orm查询指定字段_django查询mysql范围查询_05

get()方法 可以通过括号内的字段名去获取数据 
没有字段的时候会报错 不推荐使用

django查询mysql范围查询 django orm查询指定字段_数据_06

查找字段

values(字段名)筛选指定查询字段 结果是QuerySet列表套字典 
  可以用first或者last方法
values_list(字段名) 查询结果是QuerySet列表套元组

django查询mysql范围查询 django orm查询指定字段_外键_07

按字段名排序查询

order_by  (默认升序)降序('-age')传多个参数的时候 第一个字段相同 自动排第二个字段 支持多个字段排序

django查询mysql范围查询 django orm查询指定字段_字段_08

统计个数

count()  先查询所有all().count()  统计查询的对象个数

django查询mysql范围查询 django orm查询指定字段_django查询mysql范围查询_09

去重

distinct() 针对重复的数据集去重(注意主键) 数据必须完全一样才可以去重  结果是QuerySet列表套字典

django查询mysql范围查询 django orm查询指定字段_数据_10

取反

exclude 取反 针对括号内的数据取反  结果QuerySet列表套对象

django查询mysql范围查询 django orm查询指定字段_外键_11

反转

reverse()  仅对排序过的数据才可以反转 对排序的结果集做颠倒 结果是QuerySet列表套对象

django查询mysql范围查询 django orm查询指定字段_外键_12

判断是否是数据

exists()   判断结果集是否是数字  结果返回布尔值 但是几乎不用因为所有数据自带布尔值

django查询mysql范围查询 django orm查询指定字段_外键_13


修改数据

models.Userinfo.objects.filter(pk=10).update(name= 'lili')

删除数据

models.Userinfo.objects.filter(pk=1).delete()

直接编写sql语句

raw()方法

django查询mysql范围查询 django orm查询指定字段_django查询mysql范围查询_14

导模块写入方式:
    from django.db import connection  
    cursor = connection.cursor()  
    cursor.execute("insert into hello_author(name) VALUES ('郭敬明')") 
    cursor.execute("update hello_author set name='韩寒' WHERE name='郭敬明'")  
    cursor.execute("delete from hello_author where name='韩寒'")  
    cursor.execute("select * from hello_author")  
    cursor.fetchone()  
    cursor.fetchall()
双下划线查询
1.比较运算符
	字段__gt  大于
 	字段__lt  小于
 	字段__gte  大于等于
 	字段__lte  小于等于

django查询mysql范围查询 django orm查询指定字段_字段_15

2.成员运算
  __in

django查询mysql范围查询 django orm查询指定字段_外键_16

3.范围查询(针对数字)
   __range

django查询mysql范围查询 django orm查询指定字段_字段_17

4.模糊查询
   字段__contains  不忽略大小写
   字段__icontains   忽略大小写

django查询mysql范围查询 django orm查询指定字段_外键_18

5.日期处理
  字段__year
  字段__month
  字段__day

django查询mysql范围查询 django orm查询指定字段_字段_19

查看ORM底层SQL语句
# 方式一:
  如果返回的是QuerySet对象 可以直接.query 查看sql语句

django查询mysql范围查询 django orm查询指定字段_外键_20

EXTRACT()函数:
MySQL中的此函数用于从指定日期提取零件。
此方法接受两个参数: 
   部分-指定要提取的部分,例如SECOND,MINUTE,HOUR,DAY,WEEK,MONTH,YEAR等。
   日期-指定的提取日期。
返回值:它从指定日期返回所需的提取部分。

django查询mysql范围查询 django orm查询指定字段_外键_21

# 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',
                },
            }
        }

django查询mysql范围查询 django orm查询指定字段_外键_22

外键创建

表关系关键字
# 一对多  models.ForeignKey()
   ORM中外键字段建在多的一方
   会自动添加_id后缀

# 多对多  models.ManyToManyField()
ORM中有三种创建多对多字段的方式 
	方式1:直接在查询频率较高的表中填写字段即可 自动创建第三张关系表
	方式2:自己创建第三张关系表
	方式3:自己创建第三张关系表 但是还是要orm多对多字段做关联

# 一对一  models.OneToOneField()
  ORM中外键字段建在查询频率较高的表中
  会自动添加_id后缀

'''
注意版本问题:
django1.X 针对 models.ForeignKey() models.OneToOneField()不需要on_delete
django2.X 3.X 则需要添加on_delete参数'''

django查询mysql范围查询 django orm查询指定字段_数据_23

创建表
先在models里创建四张表
book,author,publish,author_detail
分别创建字段

django查询mysql范围查询 django orm查询指定字段_外键_24

外键数据的增删改查

# 一对多
1.先给book表创建数据
 publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
在models里创建 有两种方式:
  1.直接给实际字段添加关联数据值  publish_id=1
  models.Book.objects.create(title='快乐星球的小王子',price=30,publish_id=1)
  2.间接使用外键虚拟字段添加关联数据
  publish_obj = models.Publish.objects.filter(pk=4).first() # 先获取到出版社对象
  models.Book.objects.create(title='用自己的方式过一生',price=48,publish=publish_obj)
添加数据报错:
django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails

django查询mysql范围查询 django orm查询指定字段_django查询mysql范围查询_25

解决办法: 在settings的DATABASES里添加一条数据
  'OPTIONS': {"init_command": "SET foreign_key_checks = 0;"}

django查询mysql范围查询 django orm查询指定字段_外键_26

# 一对一
给作者关联数据
 author_datail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
 
 在models里创建 有两种方式
  1.直接给实际字段添加关联数据值  
  2.间接使用外键虚拟字段添加关联数据
# 多对多 (重要)  主要操作第三张表 增删改查
 authors = models.ManyToManyField(to='Author')
利用第三张表的虚拟名称  
book对象.外键字段.add()  添加数据   既可以放数字 也可以放对象
 book_obj = models.Book.objects.filter(pk=7).first()
    book_obj.authors.add(4)
book_obj = models.Book.objects.filter(pk=5).first()
author_obj = models.Author.objects.filter(pk=1).first()
    book_obj.authors.add(author_obj)
	

book对象.外键字段.remove()  删除数据   既可以放数字 也可以放对象
    book_obj.authors.remove(1)
book对象.外键字段.set() 修改数据 括号内必须是可迭代对象 iterable_obj
   book_obj.authors.set([1,3])  # set()括号内只可以放支持迭代的对象  【相当于删除加新增】
 

book_obj.authors.clear() 清空指定数据  括号不需要任何参数
  book_obj.authors.clear()  # 清除书籍对象对应的所有作者
  

  2.以对象为基准 思考正反向概念 (思考什么时候会出现None)

跨表查询

正反向概念
1.正反向概念核心就在于外键字段在哪张表
      在有外键字段的表查询 正向查询 按外键字段   
      没有外键字段的表查询 反向查询 按表名小写加_set
基于对象的跨表查询(子查询)
# 正向查询
1.查询主键为1的书籍对应的出版社名称(书查出版社) 一对多
  1.根据条件查询数据对象
book_obj = models.Book.objects.filter(pk=1).first()

  2.以对象为基准 思考正反向概念
 print(book_obj.publish.name)


2.查询主键为3的书籍对应的作者 多对多
  1.根据条件查询数据对象
book_obj = models.Book.objects.filter(pk=3).first()

  2.以对象为基准 思考正反向概念 (思考什么时候会出现None)
  '''因为多对多是有多个作者,所以返回None 需要自己点all'''
  print(book_obj.authors.all())

3.查询jerry作者的详情  一对一
  1.根据条件查询数据对象
author_obj = models.Author.objects.filter(name='jerry').first()
  2.以对象为基准 思考正反向概念
  print(author_obj.author_datail)
# 反向查询
1.查询上海出版社出版的书籍 多对多
  1.先拿出版社对象(如果是拿的是对象一定要点first)
 publish_obj = models.Publish.objects.filter(name='上海出版社').first()
  2.思考正反向  (结果打印None需要点all)、
  print(publish_obj.book_set.all())

2.查询summer写过的书籍  一对多
   1.先拿作者对象
author_obj = models.Author.objects.filter(name='summer').first()
   2.思考正反向 
  print(author_obj.book_set.all())

3.查询电话是111111的作者 一对一
  1.先查询作者详情对象
 author_detail_obj = models.AuthorDetail.objects.filter(phone=11111).first()
  2.思考正反向  (不需要加set)
  print(author_detail_obj.author)
  
  
# 总结:一对多或多对多需要反向查询需要加_set点all(),一对一不需要
基于双下划线的多表查询(连表查询)
# 正向查询
1.查询主键为3的书籍对应的出版社名称(书查出版社) 一对多 # 只能写一行代码
res = models.Book.objects.filter(pk=3).values('publish__name')

2.查询主键为3的书籍对应的作者 多对多
  # 用现有的条件点现有的表
res=models.Book.objects.filter(pk=3).values('authors__name','title')

3.查询tom作者的详情  一对一 
 res = models.Author.objects.filter(name='tom').values('author_datail__phone')
# 反向查询
1.查询北京出版社出版的书籍名称和价格 多对多
 res = models.Publish.objects.filter(name= '北京出版社').values('book__price','book__title')
 
2.查询summer写过的书籍名称和日期  一对多
res = models.Author.objects.filter(name='summer').values('book__title','book__publish_time')

3.查询电话是11111的作者 一对一
res = models.AuthorDetail.objects.filter(phone=11111).values('author__name')