ORM执行SQL语句
神奇的双下划线查询
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoorm.settings')
import django
django.setup()
from app01 import models
"""双下划线查询实战"""
# 1.查询年龄大于20的作者
res = models.Author.objects.filter(age__gt=20)
print(res)
# 结果:
# < QuerySet[ < Author: Author
object(2) >, < Author: Author
object(3) >, < Author: Author
object(4) >, < Author: Author
object(6) >] >
# 2.查询年龄小于25岁的作者
res = models.Author.objects.filter(age__lt=25)
print(res)
# 结果:
# < QuerySet[ < Author: Author
object(1) >, < Author: Author
object(3) >, < Author: Author
object(4) >] >
"""大于等于:__gte、小于等于:__lte"""
# 3.查询年龄是18,28,38的作者
res = models.Author.objects.filter(age__in=(18,28,38))
print(res)
# 结果:
# < QuerySet[ < Author: Author
object(1) >, < Author: Author
object(2) >, < Author: Author
object(6) >] >
# 4.查询作者名字中带有字母j的数据
res = models.Author.objects.filter(name__contains='j') # 区分大小写
print(res)
# 结果:
# < QuerySet[ < Author: Author
object(6) >] >
'''__icontains="j"是不区分大小写'''
# 5.查询出版年份是2022年的书籍数据
res = models.Book.objects.filter(publish_time__year=2022).values()
print(res)
# 结果:
# < QuerySet[ < Book: Book
object(1) >, < Book: Book
object(4) >, < Book: Book
object(5) >] >
main()
"""
- 只要是queryset对象就可以无限制的点queryset对象的方法
queryset.filter().values().filter().values_list().filter()...
1. .values()取到的queryset对象是这样的格式
结果:<QuerySet
[{'id': 1, 'title': '红楼梦', 'price': Decimal('99.88'),
'publish_time': datetime.date(2022, 12, 15), 'publish_id': 1},
{'id': 4, 'title': '西游记', 'price': Decimal('56.99'),
'publish_time': datetime.date(2022, 12, 20), 'publish_id': 2},
{'id': 5, 'title': '三国志', 'price': Decimal('998.00'),
'publish_time': datetime.date(2022, 12, 5), 'publish_id': 4}]>
2. .values_list()取到的queryset对象是这样的格式
结果:<QuerySet
[(1, '红楼梦', Decimal('99.88'),
datetime.date(2022, 12, 15), 1),
(4, '西游记',Decimal('56.99'),
datetime.date(2022, 12, 20), 2),
(5, '三国志', Decimal('998.00'),
datetime.date(2022, 12, 5), 4)]>
- 对django框架如果不进行时区设置,则无法对时间进行筛选,配置再settings文件
"""
ORM外键字段的创建
# ORM外键关系
一对一,一对多,多对多
# 1.创建基础表(书籍表,出版社表,作者表,作者详细)
# 2.确定外键关系
一对一 :ORM于MYSQL一致,外键字段建在查询较高的一方
一对多 :ORM的外键字段和MYSQL相同,建在多的一方
多对多 :ORM比MYSQL变化更多
-1.外键字段可以直接建在某张查询频率较高的表中
内部会自动创建第三张表用于存放关系
-2.自己创建第三张关系表并创建外键字段
# 3.ORM创建
对于一对一,一对多在同步到表中之后会自动添加_id的后缀
对于多对多,不会在表中做展示,而是创建第三张表
# 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='出版日期')
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
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='年龄')
authorDetail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
class AuthorDetail(models.Model):
# 作者详情表
phone = models.BigIntegerField(verbose_name='电话号码')
address = models.CharField(max_length=64,verbose_name='作者地址')
外键字段的相关操作
"""一对一与一对多一致"""
# 1.针对一对多,插入数据可以直接填写表中实际的字段
# models.Book.objects.create(title='本草纲目',price=123.33,publish_id=1)
# 2.针对一对多,插入数据也可以填写表中的类中字段名(既可以传数字也可以传对象)
# publish_obj = models.Publish.objects.filter(pk=1).first()
# models.Book.objects.create(title='活着', price=555.66, publish=publish_obj)
"""多对多关系绑定"""
未补全
ORM跨表查询
# 1.MYSQL连表查询思路
"""
1.子查询
分布操作
2.连表操作
先整合多张表之后基于单表查询即可
inner join 内连接
left join 左连接
right join 右连接
"""
# 2.正反向查询的概念
1.正向查询
由外键字段所在的表数据查询关联的表数据
2.反向查询
没有外键字段的表数据查询关联的表数据
ps:判断正反向就看外键字段在不在数据所在表中
# 3.ORM跨表查询口诀
正向查询按外键字段
反向查询按表名小写
基于对象的跨表查询
# 查询步骤
步骤一:先根据条件获取数据对象
步骤二:再判断正反向的概念
"""因为要考虑表名小写后获取的数据是多个,所以+_set接收"""
# 1.正向:
# 1.查询主键为1的书籍对应的出版社名称
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.name)
# 2.查询主键为4的书籍对应的作者姓名
book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors.all().values('name'))
# 3.查询tom的电话号码
author_obj = models.Author.objects.filter(name='tom').first()
print(author_obj.authorDetail.phone)
# 2.反向
# 4.查询北京出版社出版过的书籍
publish_obj = models.Publish.objects.filter(name='北京出版社').first()
print(publish_obj.book_set.all().values('title'))
# 5.查询hanser写过的书
author_obj = models.Author.objects.filter(name='hanser').first()
print(author_obj.book_set.all().values('title'))
# 6.查询电话号码是119的作者姓名
authordetail_obj = models.AuthorDetail.objects.filter(phone='119').first()
print(authordetail_obj.author.name)
基于双下划线的跨表查询
# 1.正向:
# 1.查询主键为1的书籍对应的出版社名称
res = models.Book.objects.filter(pk=1).values('publish__name','title')
print(res)
# 2.查询主键为4的书籍对应的作者姓名
res = models.Book.objects.filter(pk=4).values('title','authors__name')
print(res)
# 3.查询tom的电话号码
res = models.Author.objects.filter(name='tom').values('authorDetail__phone')
print(res)
# 2.反向
# 4.查询北京出版社出版过的书籍
res = models.Publish.objects.filter(name='北京出版社').values('book__title', 'book__price', 'name')
print(res)
# 5.查询hanser写过的书
res = models.Author.objects.filter(name='hanser').values('book__title', 'name')
print(res)
# 6.查询电话号码是119的作者姓名
res = models.AuthorDetail.objects.filter(phone=119).values('phone', 'author__name')
print(res)
依据结果表进行的进阶跨表查询
# 1.正向:
# 1.查询主键为1的书籍对应的出版社名称
res = models.Publish.objects.filter(book__pk=1).values('name')
print(res)
# 2.查询主键为4的书籍对应的作者姓名
res = models.Author.objects.filter(book__pk=4).values('name','book__title')
print(res)
# 3.查询tom的电话号码
res = models.AuthorDetail.objects.filter(author__name='tom').values('phone')
print(res)
# 2.反向
# 4.查询北京出版社出版过的书籍
res = models.Book.objects.filter(publish__name='北京出版社').values('title','price')
print(res)
# 5.查询hanser写过的书
res = models.Book.objects.filter(authors__name='hanser').values('title')
print(res)
# 6.查询电话号码是119的作者姓名
res = models.Author.objects.filter(authorDetail__phone=110).values('name')
print(res)
ORM查询总结
# 1.查询主键为4的书籍对应的作者的电话号码
res = models.Book.objects.filter(pk=4).values('authors__authorDetail__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('authorDetail__phone')
print(res)