Django查询数据
神奇的双下划线查询
双下划线查询语法
大于 : __gt
小于 : __lt
大于等于 : __gte
小于等于 : __lte
或者 : __in in走索引 not in 不走索引
之间 : __range
模糊查询 : __contains
区分大小写 : __contains
忽略大小写 : __icontains
以什么开头 : __startswith
以什么结尾 : __endswith
查询注册时间 : register_time__year
双下划线查询
# 1.查询年龄大于20的用户
res = models.User.objects.filter(age__gt=20)
# 2.查询年龄是18、22、25的用户
res = models.User.objects.filter(age__in[18,22,25])
# 3.查询年龄在18到26之间的用户
res = models.User.objects.filter(age__range=[18,26])
# 4.查询姓名中包含字母j的用户
res = models.User.objects.filter(name__contains='j')
res = models.User.objects.filter(name__icontains='j')
'''
__contains 区分大小写
__icontains 忽略大小写
'''
# 5.查询月份是5月的数据
res.models.User.objects.filter(time__year=2022)
"""
__year 按照年份筛选数据
__month 按照月份筛选数据
"""
# 6.以字符开头
res = models.User.objects.filter(name__startswith='j')
# 7.以字符结尾
res1 = models.User.objects.filter(name__endswith='j')

外键字段的创建
django orm创建表关系
图书表
出版社表
作者表
作者详情表
关系判断
书与出版社
一本书不能对应多个出版社
一个出版社可以对应多本书
# 一对多关系 书是多 出版社是一 ForeignKey
'''django orm外键字段针对一对多关系也是建在多的一方 '''
书与作者
一本书可以对应多个作者
一个作者可以对应多本书
# 多对多关系 ManyToManyField
'''django orm外键字段针对多对多关系 可以不用自己创建第三张表'''
作者与作者详情
一个作者不能对应多个作者详情
一个作者详情不能对个多个作者
# 一对一关系 OneToOneField
'''django orm外键字段针对一对一关系 建在查询频率较高的表中'''
ManyToManyField不会在表中创建实际的字段 而是告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField会在字段的后面自动添加_id后缀 如果你在定义模型类的时候自己添加了该后缀那么迁移的时候还会再次添加_id_id 所以不要自己加_id后缀
ps:三个关键字里面的参数
to用于指定跟哪张表有关系 自动关联主键
to_field\to_fields 也可以自己指定关联字段
外键字段的操作
# 一对多、一对一外键字段操作
# 增
models.Book.objects.create(title='新东方', price=5646.21,publish_id=3)
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Book.objects.create(title='雪鹰领主', price=563.21, publish=publish_obj)
# 改
models.Publish.objects.filter(pk=1).update(publish_id=2)
publish_obj = models.Publish.objects.filter(pk=1).first()
models.Publish.objects.filter(pk=1).update(publish=publish_obj)
# 多对多字段操作
1.第三张关系表创建数据
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.add()
括号内可以放主键值也可以放数据对象 并且都支持多个
2.第三张关系表修改数据
book_obj.authors.set()
book_obj.authors.set([1,])
括号内必须是一个可迭代对象 元素同样支持主键值或者数据对象
3.第三张关系表删除数据
book_obj.authors.remove()
括号内可以放主键值也可以放数据对象 并且都支持多个
4.第三张关系表清空指定数据
book_obj.authors.clear()
括号内无需传值 直接清空当前表在第三张关系表中的绑定记录
前期建表准备
from django.db import models
# Create your models here.
# 书籍
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8,decimal_places=2)
publish_data = models.DateField(auto_now_add=True)
# 一对多(出版社对书籍)
publish = models.ForeignKey(to='Publish')
# 多对多
authors = models.ManyToManyField(to='Author')
# 出版社
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
# 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
# 一对一
author_detail = models.OneToOneField(to='AuthorDetail')
# 作者详情
class AuthorDetail(models.Model):
phone = models.BigIntegerField() # 电话号码用BigIntegerField或者直接用CharField
addr = models.CharField(max_length=64)

多表查询
# 正反向概念
核心在于当前数据对象是否含有外键字段
有则是正向 没有则是反向
# 正向
由书籍查询出版社 外键字段在书籍表中 那么书查出版社就是'正向'
由书籍查询作者 外键字段在书籍表中 那么书查作者就是'正向'
由作者查询作者详情 外键字段在作者表中 那么也是'正向'
# 反向
由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'
# 查询口诀
正向查询按外键字段名
反向查询按表名小写_set
'''
当你的查询结果有多个的时候就需要加.all()
如果是一个则直接拿到数据对象
'''
# .all()应用场景
1.书籍只能对应一个出版社 不需要.all()
2.书籍可以有可以作者 需要.all()
3.作者只能有一个作者详细信息 不需要.all()
基于对象的跨表查询
# 1.查询书籍为斗破苍穹的出版社名称
获取书籍对象
book_obj = models.Book.objects.filter(title='斗破苍穹').first()
res = book_obj.publish
print(res) # Publish object
print(res.name) # 南方出版社
print(res.addr) # 南方
# 2.查询斗罗大陆对应的作者
book_obj = models.Book.objects.filter(title='斗罗大陆').first()
res = book_obj.authors # app01.Author.None
res = book_obj.authors.all() # <QuerySet [<Author: Author object>]>
# 3.查询作者jason的详情信息
author_obj = models.Author.objects.filter(name='jason').first()
res = author_obj.author_detail
print(res) # AuthorDetail object
print(res.addr) # 芜湖
# 4.查询东方出版社出版的书籍
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
res = publish_obj.book_set # app01.Book.None
res = publish_obj.book_set.all() # <QuerySet [<Book: Book object>]>
# 5.查询电话是110的作者
author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
res = author_detail_obj.author # 作者对象:jason
'''
正向什么时候需要加.all()
当你的结果可能有多个的时候就需要加.all()
如果是一个则直接拿到数据对象
'''

基于双下划线的跨表查询
"""基于双下划线的跨表查询本质就是连表操作"""
# 1.查询斗破苍穹书籍对应的出版社名称
res = models.Book.objects.filter(title='斗破苍穹').values('publish__name','publish__addr')
<QuerySet [{'publish__name': '南方出版社', 'publish__addr': '南京'}]>
# 2.查询斗罗大陆对应的作者
res = models.Book.objects.filter(title='斗罗大陆').values('authors__name')
<QuerySet [{'authors__name': 'kevin'}]>
# 3.查询作者jason的手机号和地址
res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
<QuerySet [{'author_detail__phone': 110, 'author_detail__addr': '芜湖'}]>
# 4.查询东方出版社出版的书籍名称和价格
res = models.Publish.objects.filter(name='东方出版社').values('book__title','book__price')
<QuerySet [{'book__title': '雪鹰领主', 'book__price': Decimal('563.21')}]>
# 5.查询电话是110的作者的姓名和年龄
res = models.AuthorDetail.objects.filter(phone=110).values('author__name','author__age')
<QuerySet [{'author__name': 'jason', 'author__age': 18}]>
双下线查询扩展
"""基于双下划线的跨表查询的结果也可以是完整的数据对象"""
'''手上有条件所在的表可以不被models点 直接点最终的目标数据对应的表'''
# 1.查询斗破苍穹书籍对应的出版社名称
res = models.Publish.objects.filter(book__title='斗破苍穹')
<QuerySet [<Publish: Publish object>]>
res = models.Publish.objects.filter(book__title='斗破苍穹').values('name')
<QuerySet [{'name': '南方出版社'}]>
# 2.查询斗罗大陆对应的作者姓名和年龄
res = models.Author.objects.filter(book__title='斗罗大陆').values('name','age')
<QuerySet [{'name': 'kevin', 'age': 28}]>
# 3.查询作者jason的手机号和地址
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','addr')
<QuerySet [{'phone': 110, 'addr': '芜湖'}]>
'连续跨表操作'
# 查询斗罗大陆对应作者的手机号
res = models.AuthorDetail.objects.filter(author__book__title='斗罗大陆').values('phone')
res = models.Book.objects.filter(title='斗罗大陆').values('authors__author_detail__phone')
<QuerySet [{'authors__author_detail__phone': 120}]>
如何查看SQL语句
# 方式1:如果结果集对象是queryset 那么可以直接点query查看
res = models.User.objects.values_list('name', 'age')
print(res.query) # 查看内容封装的SQL语句
SELECT `app01_user`.`name`, `app01_user`.`age` FROM `app01_user`
# 方式2:配置文件固定配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console':{
'level':'DEBUG',
'class':'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level':'DEBUG',
},
}
}
