Django---外键创建,表查询
双下划线查询
filter里是不能写逻辑运算符的,而是给定了一个特定的方法去提供逻辑查询,那就是双下划线。
方法 | 功能 |
---|---|
__gt | 大于 |
__lt | 小于 |
__gte | 大于等于 |
__lte | 小于等于 |
__in | 成员运算 |
__range | 范围查询 |
__contains | 模糊查询,区分大小写 |
__icontains | 模糊查询,忽略大小写 |
__startswith | 匹配开头 |
__endswith | 匹配结尾 |
__regex | 正则表达式 |
__year | 按照年份筛选数据 |
__month | 按照月份筛选数据 |
例题展示:在需要查询的字段后添加双下划线方法查询。
# 1.查询年龄大于20的用户
res = models.User.objects.filter(age__gt=20)
print(res)
# 2.查询年龄是18、22、25的用户
res = models.User.objects.filter(age__in=[18, 22, 25])
print(res)
# 3.查询年龄在18到26之间的用户
res = models.User.objects.filter(age__range=[18, 26]) # 包含18和26
print(res)
# 4.查询姓名中包含字母j的用户
res = models.User.objects.filter(name__contains='j')
res = models.User.objects.filter(name__icontains='j')
print(res)
# 5.查询月份是5月的数据
res = models.User.objects.filter(op_time__month=5)
print(res)
res = models.User.objects.filter(op_time__year=2022)
print(res)
外键字段的创建
复习MySQL外键知识。
关系 | 外键位置 |
---|---|
一对多关系 | 外键字段建在多的一方 |
多对多关系 | 外键字段建在第三张关系表中 |
一对一关系 | 外键字段建在任意一方都可以,但是推荐建在查询频率较高的表中 |
Django中的外键创建和mysql几乎一样,我们以创建图书表,出版社表,作者表和作者详情表来举例子。
两张表 | 关系 | 方法 | 外键位置 |
---|---|---|---|
书与出版社 | 一对多关系 | ForeignKey(to='出版社表') | 一对多关系也是建在多的一方,建在书的表里 |
书与作者 | 多对多关系 | ManyToManyField(to='作者表') | 多对多关系,可以不用自己创建第三张表 |
作者与作者详情 | 一对一关系 | OneToOneField=(to='作者详情表') | 一对一关系,建在查询频率较高的表中,建在作者表里 |
ps:三个关键字里面的参数,to用于指定跟哪张表有关系,自动关联主键。to_field\to_fields,也可以自己指定关联字段。
ManyToManyField不会在表中创建实际的字段,而是告诉django orm自动创建第三张关系表。ForeignKey、OneToOneField会在字段的后面自动添加_id后缀,如果你在定义模型类的时候自己添加了该后缀那么迁移的时候还会添加,所以不要自己加下划线id后缀。
创建的具体代码:
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.DateTimeField(auto_now_add=True,verbose_name='出版日期')
# 书和出版社的外键字段 一对多
publish=models.ForeignKey(to='Publish') # 默认关联的是主键
# 书和作者的外键字段 多对多
authors=models.ManyToManyField(to='Author') # 自动创建书和作者的第三张关系表
def __str__(self):
return f'书籍对象:{self.title}'
class Publish(models.Model):
'''出版社'''
name=models.CharField(max_length=32,verbose_name='出版社名称')
addr=models.CharField(max_length=32,verbose_name='出版社地址')
def __str__(self):
return f'出版社对象:{self.name}'
class Author(models.Model):
''''作者'''
name=models.CharField(max_length=32,verbose_name='作者姓名')
age=models.IntegerField(verbose_name='年龄')
# 作者和作者详情的外键关系 一对一
authorDetail=models.OneToOneField(to='AuthorDetail')
def __str__(self):
return f'作者对象:{self.name}'
class AuthorDetail(models.Model):
'''作者详情'''
phone=models.BigIntegerField(verbose_name='手机号')
addr=models.CharField(max_length=32,verbose_name='家庭地址')
def __str__(self):
return f'作者详情:{self.addr}'
外键字段操作
一对多、一对一外键字段操作
新增数据
方法1:
models.Book.objects.create(title='聊斋志异', price=16987.22, publish_id=1) # 直接填写关联数据的主键值
方法2:
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='资本论', price=56777.98, publish=publish_obj) # 传一个数据对象
修改关系字段
models.Book.objects.filter(pk=1).update(publish_id=3)
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.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() # 括号内必须是一个可迭代对象,元素同样支持主键值或者数据对象
3.第三张关系表删除数据
book_obj.authors.remove() # 括号内可以放主键值也可以放数据对象 并且都支持多个
4.第三张关系表清空指定数据
book_obj.authors.clear() # 括号内无需传值 直接清空当前表在第三张关系表中的绑定记录
多表查询之正反向
MySQL多表查询思路:
子查询:将SQL语句用括号括起来当做条件使用
连表操作:inner join\left join\right join\union.
django orm本质还是使用的上述两种方法:
子查询:基于对象的跨表查询
连表操作:基于双下划线的跨表查询
正反向的概念
核心在于当前数据对象是否含有外键字段,有则是正向,没有则是反向。
正向
由书籍查询出版社 外键字段在书籍表中 那么书查出版社就是'正向'
由书籍查询作者 外键字段在书籍表中 那么书查作者就是'正向'
由作者查询作者详情 外键字段在作者表中 那么也是'正向'
反向
由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'
查询口诀:正向查询按外键字段名,反向查询按表名小写.
基于对象的跨表查询
基于对象的跨表查询本质就是子查询即分步操作即可,我们已例题为例子。
1.查询数据分析书籍对应的出版社(正向)
# 先获取书籍对象
book_obj = models.Book.objects.filter(title='数据分析').first()
# 再使用跨表查询
res = book_obj.publish
print(res) # 出版社对象:北方出版社
2.查询python全栈开发对应的作者(正向)
# 先获取书籍对象
book_obj = models.Book.objects.filter(title='python全栈开发').first()
# 再使用跨表查询
res = book_obj.authors # app01.Author.None 因为书和作者是多对多的关系,所以需要在个all()
res = book_obj.authors.all()
print(res) # <QuerySet [<Author: 作者对象:jason>, <Author: 作者对象:jerry>]>
3.查询作者jason的详情信息(正向)
# 先获取jason作者对象
author_obj = models.Author.objects.filter(name='jason').first()
# 再使用跨表查询
res = author_obj.author_detail
print(res) # 作者详情对象:芜湖
4.查询东方出版社出版的书籍(反向)
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
# 反向查询表面小写加_set
# res = publish_obj.book_set # app01.Book.None
res = publish_obj.book_set.all()
print(res) # <QuerySet [<Book: 书籍对象:linux云计算>, <Book: 书籍对象:聊斋志异>]>
5.查询jason编写的书籍
author_obj = models.Author.objects.filter(name='jason').first()
# res = author_obj.book_set # app01.Book.None
res = author_obj.book_set.all()
print(res) # <QuerySet [<Book: 书籍对象:python全栈开发>]>
6.查询电话是110的作者
phone_obj=models.AuthorDetail.objects.filter(phone=110).first()
res=phone_obj.author
print(res)
基于双下划线的跨表查询
基于双下划线的跨表查询本质就是连表操作。
1.查询数据分析书籍对应的价格和出版日期(正向)
res = models.Book.objects.filter(title='数据分析').values('publish__name', 'publish__addr')
print(res) # <QuerySet [{'publish__name': '北方出版社', 'publish__addr': '北京'}]>
2.查询python全栈开发对应的作者姓名和年龄
res = models.Book.objects.filter(title='python全栈开发').values('authors__name','authors__age')
print(res) # <QuerySet [{'authors__name': 'jason', 'authors__age': 18}, {'authors__name': 'jerry', 'authors__age': 29}]>
3.查询作者jason的手机号和地址
res = models.Author.objects.filter(name='jason').values('author_detail__phone','author_detail__addr')
print(res) # <QuerySet [{'author_detail__phone': 110, 'author_detail__addr': '芜湖'}]>
4.查询东方出版社出版的书籍名称和价格
res = models.Publish.objects.filter(name='东方出版社').values('book__title','book__price')
print(res) # <QuerySet [{'book__title': 'linux云计算', 'book__price': Decimal('24888.44')}, {'book__title': '聊斋志异', 'book__price': Decimal('16987.22')}]>
5.查询jason编写的书籍名称和日期
res = models.Author.objects.filter(name='jason').values('book__title', 'book__publish_time')
print(res) # <QuerySet [{'book__title': 'golang高并发', 'book__publish_time': datetime.date(2022, 6, 7)}, {'book__title': 'python全栈开发', 'book__publish_time': datetime.date(2022, 2, 28)}]>
6.查询电话是110的作者的姓名和年龄
res = models.AuthorDetail.objects.filter(phone=110).values('author__name','author__age')
print(res) # <QuerySet [{'author__name': 'jason', 'author__age': 18}]>
双下线查询扩展
基于双下划线的跨表查询的结果也可以是完整的数据对象,手上有条件所在的表可以不被models点,直接点最终的目标数据对应的表。
1.查询数据分析书籍对应的出版社名称
res = models.Publish.objects.filter(book__title='数据分析')
print(res) # <QuerySet [<Publish: 出版社对象:北方出版社>]>
res = models.Publish.objects.filter(book__title='数据分析').values('name')
print(res) # <QuerySet [{'name': '北方出版社'}]>
2.查询python全栈开发对应的作者姓名和年龄
res = models.Author.objects.filter(book__title='python全栈开发').values('name','age')
print(res) # <QuerySet [{'name': 'jason', 'age': 18}, {'name': 'jerry', 'age': 29}]>
3.查询作者jason的手机号和地址
res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','addr')
print(res) # <QuerySet [{'phone': 110, 'addr': '芜湖'}]>
4.查询东方出版社出版的书籍名称和价格
res = models.Book.objects.filter(publish__name='东方出版社').values('title','price')
print(res) # <QuerySet [{'title': 'linux云计算', 'price': Decimal('24888.44')}, {'title': '聊斋志异', 'price': Decimal('16987.22')}]>
5.查询jason编写的书籍名称和日期
res = models.Book.objects.filter(authors__name='jason').values('title','publish_time')
print(res) # <QuerySet [{'title': 'golang高并发', 'publish_time': datetime.date(2022, 6, 7)}, {'title': 'python全栈开发', 'publish_time': datetime.date(2022, 2, 28)}]>
6.查询电话是110的作者的姓名和年龄
res = models.Author.objects.filter(author_detail__phone=110).values('name','age')
print(res) # <QuerySet [{'name': 'jason', 'age': 18}]>
7.连续跨表操作:查询python全栈开发对应的作者的手机号
res1 = models.AuthorDetail.objects.filter(author__book__title='python全栈开发').values('phone')
print(res1) # <QuerySet [{'phone': 110}, {'phone': 140}]>
如何查看SQL语句
方式1:如果结果集对象是queryset 那么可以直接点query查看
方式2:配置文件固定配置,在settings.py里添加配置。适用面更广,只要执行了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',
},
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用