Django ORM 常用字段和表查询

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

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    查找主键 不需要输入主键真正的名字 (适用于主键名较长或者不知道主键名的情况下)

image

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

查询所有的数据:

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

image

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

image
image

查询第一个和最后一个

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

image

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

image

查找字段

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

image

按字段名排序查询

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

image

统计个数

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

image

去重

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

image

取反

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

image

反转

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

image

判断是否是数据

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

image
修改数据

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

删除数据

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

直接编写sql语句

raw()方法

image

导模块写入方式:
    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  小于等于

image

2.成员运算
  __in 
  

image

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

image

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

image

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

image

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

image

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

image

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

image

外键创建

表关系关键字
# 一对多  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参数'''

image

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

image

外键数据的增删改查

# 一对多
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 

image

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

image

# 一对一
给作者关联数据
 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')
posted @ 2022-09-05 23:22  Hsummer  阅读(261)  评论(0编辑  收藏  举报