ORM执行SQL语句
有时候ORM的操作效率可能偏低,其实也支持自己写SQL语句
#方式1:
#注意表名
res = models.User.objects.raw('select * from app01_user where id<3;')
print(list(res))
"""
[<User: 用户对象:jason>, <User: 用户对象:torry>]
"""
#方式2:
from django.db import connection
cursor = connection.cursor()
cursor.execute('select name from app01_user where id<4;')
# print(cursor.fetchall())
"""
(('jason',), ('torry',), ('kevin',))
"""
print(cursor.fetchone())
print(cursor.fetchone())
"""
('jason',)
('torry',)
"""
神奇的双下划线查询
以下直接打印res返回的结果是QuerySet数据对象
只要还是queryset对象,就可以无限制的去点queryset对象的方法
(1)比较运算符
字段__gt # 大于
字段__gte # 大于等于
字段__lt # 小于
字段__lte # 小于等于
#查询年龄大于18的数据
res = models.User.objects.filter(age__gt=18)
#查询年龄大于等于18的数据
res = models.User.objects.filter(age__gte=18)
(2)成员运算
字段__in=() # 在某几个数据中 可以给多个值
#查询年龄是18、28、38的数据
res = models.User.objects.filter(age__in=(18,28,38))
(3)范围查询
字段__range=[] # 在某个范围内 最多给两个值
#查询年龄在10~20之间的数据(包含10和20)
res = models.User.objects.filter(age__range=(10,20))
(4)模糊查询
字段__contains # 区分大小写
字段__icontains # 不区分大小写
#查询姓名中有字母j的数据
res = models.User.objects.filter(name__contains='j')
(5)日期处理
需注意settings.py中时间为UTC时间,所以月和日不准
。后面BBS项目再改
字段__year # 年
字段__month # 月
字段__day # 日
#查询注册年份是2022的数据
res = models.User.objects.filter(register_time__year=2022)
ORM外键字段的创建
"""
复习MySQL外键关系
一对多
外键字段建在多的一边
多对多
外键字段键在第三张关系表中
一对一
外键字段键在查询频率较高的表中
"""
(1)前期准备
1.cmd中创建库
create database 库名;
2.settings.py配置文件中把库sqlite3改为mysql
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'day06', # 库名
'USER': 'root',
'PASSWORD': '123',
'HOST': '127.0.0.1',
'PORT': 3306,
'CHARSET': 'utf8'}
创建模型类补充知识
#小数字段:
DecimalField #小数
#小数字段参数:
max_digits=8 #总共8位
decimal_places=2 #小数点后占2位
————————————————————————————————————————
创建完表后建议用"""图书表"""标注一下
————————————————————————————————————————
3.模型层models.py中写入模型类(写4张表)
class Book(models.Model):
"""图书表"""
title = models.CharField(max_length=32, verbose_name='书名')
price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name='价格')
publish_time = models.DateField(auto_now_add=True, verbose_name='出版日期')
class Publish(models.Model):
"""出版社表"""
name = models.CharField(max_length=32, verbose_name='出版社名字')
address = models.CharField(max_length=64, verbose_name='地址')
class Author(models.Model):
"""作者表"""
name = models.CharField(max_length=32, verbose_name='作者')
age = models.IntegerField(verbose_name='年龄')
class AuthorDetail(models.Model):
"""作者详情表"""
phone = models.BigIntegerField(verbose_name='手机号')
address = models.CharField(max_length=64, verbose_name='家庭住址')
4.分析四张表的表关系 确定外键字段建在哪里
# 图书表 与 出版社表
一本书对应多个出版社 ×
一个出版社对应多本书 √
一对多,书为多,外键在多(书)
#ForeignKey
————————————————————————————————
# 图书表 与 作者表
一本书对应多个作者 √
一个作者对应多本书 √
多对多,书频率高,外键在书
'需有绑定两个表关系的第三张表'
#ManyToManyField
————————————————————————————————
# 作者表 与 作者详情表
一个作者对应多个作者详情 ×
一个作者详情对应多个作者 ×
一对一,作者频率高,外键在作者
#OneToOneField
创建外键字段补充知识
一对多、一对一会给外键字段名自动加一个_id后缀`
`多对多不会只是虚拟字段,不会在表中显示,会去创建第三张表
#创建一对多外键字段
publish = models.ForeignKey(to='关联的类名(表)',on_delete=models.CASCADE)
"""
ORM在表中会自动给publish加一个_id后缀用来表示是该表的外键
on_delete=models.CASCADE 级联删除
django1.X版本所有外键字段默认都是级联更新级联删除
django2.X版本及以上需自己声明
"""
————————————————————————————————————————————————
#创建多对多外键字段
author = models.ManyToManyField(to='关联的类名(表)')
"""
多对多外键字段为虚拟字段,表中看不到该字段。用来告诉ORM自动创建第三张表
多对多不需要声明级联更新级联删除
ORM比SQL有更多优化
1.外键字段可以在某张表中(查询频率最高的)
内部会自动创建第三张表关系 (表名:app01_表1_表2)
2.自己创建第三张关系表,并自己创建两个外键字段
其实也可以写外键,后续会了解
PS:暂不考虑第二种方式
"""
——————————————————————————————————————————
#创建一对一外键字段
author_detail=models.OneToOneField(to='关联的类名(表)',on_delete=models.CASCADE)
"""
ORM在表中会自动给author_detail加一个_id后缀用来表示是该表的外键
on_delete=models.CASCADE 级联删除
django1.X版本所有外键字段默认都是级联更新级联删除
django2.X版本及以上需自己声明
"""
5.给需要的表添加外键字段
#【Book图书表】:
# 创建书籍与出版社的一对多外键字段
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
# 创建书籍与作者表的多对多外键字段
author = models.ManyToManyField(to='Author')
——————————————————————————————————————————————
#【Author作者表】:
# 创建作者与作者详情表的一对一外键字段
author_detail=models.OneToOneField(to='AuthorDetail',on_delete=models.CASCADE)
6.写完模型类后执行数据库迁移命令
python38 manage.py makemigrations
python38 manage.py migrate
外键字段数据的增改删
(1)前期准备
1.先给三张表提前录入需要的数据 图书表、图书与作者关系的第三张表用orm操作
#【app01_authordetail作者详情表】
录入数据
#【app01_author作者表】
录入数据
#【app01_publish出版社表】
录入数据
2.搭建测试环境
import os
import sys
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoday06.settings')
import django
django.setup()
(2)增
①一对一和一对多
create()
增
给图书表app01_book增数据
1.#可直接填写表中的字段名添加主键
models.Book.objects.create(title='三国演义',price=88.88,publish_id=1)
2.#也可填写对应的对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='水浒传',price=66.66,publish=publish_obj)
②多对多
add()
增
给 书跟作者的第三张关系表app01_book_author增数据
由于给某张表中添加数据需要用models去点一个表,发现自动创建的第三张关系表没办法点出来。所以就要想其他办法:需要获取一个含有多对多关系字段的数据对象即可
(书籍表中有一个authors
虚拟字段,所以获取书籍对象即可)
1.#找到含有多对多关系字段的对象 然后在第三张表中绑定关系
book_obj=models.Book.objects.filter(pk=1).first()#找到id=1的书籍对象
book_obj.author.add(1) #在第三张关系表中给该书籍对象绑定作者id
book_obj.author.add(2,3)#且支持绑定多个作者id
2.#也可以填写作者对象
book_obj=models.Book.objects.filter(pk=2).first()#找到id=2的书籍对象
author_obj1=models.Author.objects.filter(pk=1).first()#找id=1的作者对象
author_obj2=models.Author.objects.filter(pk=2).first()#找id=2的作者对象
book_obj.author.add(author_obj1,author_obj2)#在第三张表中给该书籍对象绑定作者对象
"""
orm会自动识别对象或id绑定
"""
(3)改
注意:set([])中必须跟列表或元组
①多对多
set([])或set(())
修改
1.#找到要修改外键绑定关系的书籍对象 然后在第三张表中修改关系
book_obj=models.Book.objects.filter(pk=1).first()#找到对应id的书籍对象
book_obj.author.set([1,])#在第三章表中修改绑定关系
"""
注意:如果没有该关系则是先删除再新增
"""
2.#也可以填写作者对象
book_obj=models.Book.objects.filter(pk=2).first()#找到对应id的书籍对象
author_obj=models.Author.objects.filter(pk=3).first()#找到对应id的作者对象
book_obj.author.set([author_obj])#在第三章表中修改绑定关系
(4)删
①多对多
remove()
删
clear()
清空
1.#找到要删除绑定关系的书籍对象 然后在第三张表中修改关系
book_obj=models.Book.objects.filter(pk=1).first()
book_obj.author.remove(2,3)#在第三章表中修改绑定关系
2.#也可以填写作者对象
book_obj=models.Book.objects.filter(pk=2).first()
author_obj=models.Author.objects.filter(pk=3).first()
book_obj.author.remove(author_obj)
3.#直接把某本书的所有关系清空
book_obj=models.Book.objects.filter(pk=2).first()
book_obj.author.clear()
8)ORM跨表查询
"""
复习MySQL跨表查询
子查询
分步操作:将一条SQL语句用括号括起来当作另外一条SQL语句的条件
连表操作
先整合多张表之后基于单表查询
inner join 内连接
left join 左连接
right join 右连接
"""
正反向查询的概念(重要)
#正向查询
由外键字段所在的表数据查询关联的表数据 正向
'通过书查询出版社 外键字段在书表中'
#反向查询
没有外键字段的表数据查询关联的表数据 反向
'通过出版社查询书 外键字段不在出版社表中'
#ps:正反向的核心就看外键字段在不在当前数据所在的表中
"""
ORM跨表查询的口诀:
正向查询按外键字段 (模型类里写的外键字段)
反向查询按表名小写_set (当结果可能是多的时候用_set.all(),单个时不用加)
"""
(1)基于对象的跨表查询
'''基于对象的正向跨表查询'''
1.查询主键为1的书籍对应的出版社名称
# 先根据条件获取数据对象
book_obj = models.Book.objects.filter(pk=1).first()
# 再判断正反向的概念 由书查出版社 外键字段在书所在的表中 所以是正向查询
# print(book_obj.publish) # Publish object (1)
print(book_obj.publish.name) # 北方出版社
2.查询主键为1的书籍对应的作者姓名
# 先根据条件获取数据对象
book_obj = models.Book.objects.filter(pk=1).first()
# 再判断正反向的概念 由书查作者 外键字段在书所在的表中 所以是正向查询
# print(book_obj.authors) # app01.Author.None
# print(book_obj.authors.all())
# <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
# 如果在模型表modles.py中写了__str__方法 可打印出对象的名字
print(book_obj.authors.all().values('name'))
# <QuerySet [{'name': 'zy'}, {'name': 'mm'}]>
3.查询jason的电话号码
author_obj = models.Author.objects.filter(name='jason').first()
print(author_obj.author_detail.phone)
'''基于对象的反向跨表查询'''
4.查询北方出版社出版过的书籍
# 先根据条件获取数据对象
publish_obj = models.Publish.objects.filter(name='北方出版社').first()
# 再判断正反向的概念 由出版社查书 外键字段在书所在的表中 所以是反向查询
# print(publish_obj.book_set) # app01.Book.None
print(publish_obj.book_set.all().values('title'))
5.查询jason写过的书籍
author_obj = models.Author.objects.filter(name='jason').first()
# print(author_obj.book_set) # app01.Book.None
print(author_obj.book_set.all().values('title'))
6.查询电话号码是110的作者姓名
authordetail_obj=models.AuthorDetail.objects.filter(phone=110).first()
print(authordetail_obj.author.name)
(2)基于双下划线的跨表查询
'''基于双下划线的正向跨表查询'''
1.查询主键为1的书籍对应的该书籍名称和出版社名称
# 先根据条件获取数据对象 然后判断书籍和出版社是正向查询 values里支持之反向__字段名获取值
res=models.Book.objects.filter(pk=1).values('title','publish__name')
print(res)
2.查询主键为3的书籍对应的该书籍名称和作者姓名
res=models.Book.objects.filter(pk=3).values('title','author__name')
print(res)
3.查询jason的电话号码
res=models.Author.objects.filter(name='jason').values('author_detail__phone')
print(res)
'''基于双下划线的反向跨表查询'''
4.查询北方出版社出版过的书籍名称和价格
res=models.Publish.objects.filter(name='北方出版社').values('book__title','book__price')
print(res)
5.查询jason写过的书籍名称
res=models.Author.objects.filter(name='jason').values('book__title')
print(res)
6.查询电话号码是110的作者姓名
res=models.AuthorDetail.objects.filter(phone=110).values('author__name')
print(res)
(3)进阶操作
如果不能用已知的条件去查,则需要用另一个已知去推,(原本正向变成了反向)
'''原本正向变反向'''
1.查询主键为1的书籍对应的出版社名称
# 用第二张表里筛选中反向操作获取对象 然后values取自己表中的数据
res=models.Publish.objects.filter(book__pk=1).values('name')
print(res)
2.查询主键为3的书籍对应的作者姓名
res=models.Author.objects.filter(book__pk=3).values('name')
print(res)
3.查询jason的电话号码
res=models.AuthorDetail.objects.filter(author__name='jason').values('phone')
print(res)
'''原本反向变正向'''
4.查询北方出版社出版过的书籍名称和价格
res=models.Book.objects.filter(publish__name='北方出版社').values('title','price')
print(res)
5.查询jason写过的书籍名称
res=models.Book.objects.filter(author__name='jason').values('title')
print(res)
6.查询电话号码是110的作者姓名
res=models.Author.objects.filter(author_detail__phone=110).values('name')
print(res)
# 三表:查询主键为1的书籍对应的作者的电话号码
#支持跨表查询,当查到作者表时,可继续点外键字段获取电话号
方法一:res=models.Book.objects.filter(pk=1).values('author__author_detail__phone')
print(res)
方法二:res = models.AuthorDetail.objects.filter(author__book__pk=4).values('phone')
print(res)
方法三:res = models.Author.objects.filter(book__pk=4).values('author_detail__phone')
print(res)
标签:__,框架,author,models,res,django,filter,objects
From: https://www.cnblogs.com/lvqingmei/p/16990372.html