Django day06(双下划线查询、外键字段操作、多表查询)

双下划线查询

'例:filter(age__gt=20)'
	'字段__查询方式=值'
__gt		>
__lt		<
__gte		≥
__lte		≤
__in		成员运算
__range		范围查询
__contains	模糊查询	区分大小写
__icontains	        忽略大小写
__startwith	以...开头
__endwith	以...结尾
__regex		正则
__year		按照年份筛选
__month		按照月份筛选
...
1.查询年龄大于20的用户
	res = models.User.objects.filter(age__gt=20)
	print(res)

2.查询年龄是182225的用户
	res = models.User.objects.filter(age__in=[18, 22, 25])
	print(res)

3.查询年龄在1826之间的用户
	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)
    
# 查询年份是22年的数据
	res = models.User.objects.filter(op_time__year=2022)
	print(res)

orm创建外键字段

django orm创建表关系

'models.py'内orm建表

  图书表		Book
  出版社表	Publish
  作者表		Author
  作者详情表	AuthorDetail

关系判断

1.书与出版社
    一本书不能对应多个出版社
    一个出版社可以对应多本书
# 一对多关系 书是多 出版社是一
# ForeignKey
    '''django orm外键字段针对一对多关系也是建在多的一方 '''    
2.书与作者
    一本书可以对应多个作者
    一个作者可以对应多本书
# 多对多关系 		
# ManyToManyField
    '''django orm外键字段针对多对多关系 可以不用自己创建第三张表'''
3.作者与作者详情
    一个作者不能对应多个作者详情
    一个作者详情不能对个多个作者
# 一对一关系				
# OneToOneField
    '''django orm外键字段针对一对一关系 建在查询频率较高的表中'''
1.ManyToManyField不会在表中创建实际的字段
而是告诉django orm自动创建第三张关系表

2.ForeignKey、OneToOneField会在字段的后面自己添加_id后缀 
'不要自己加_id 否则会成_id_id'

ps:三个关键字里面的参数
    to用于指定跟哪张表关联 自动关联主键
    to_field\to_fields  也可以自己指定关联字段
建表代码
from django.db import models

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')   # 默认关联的就是主键字段
    # 书与作者的外键字段    多对多
    authors = models.ManyToManyField(to='Author')   # 自动创建书和作者的第三张关系表

    def __str__(self):
        return '书籍对象:%s' % self.title


class Publish(models.Model):
    name = models.CharField(max_length=32, verbose_name='出版社名')
    addr = models.CharField(max_length=64, verbose_name='出版社地址')

    def __str__(self):
        return '出版社对象:%s' % self.name


class Author(models.Model):
    name = models.CharField(max_length=32, verbose_name='作者名')
    age = models.IntegerField(verbose_name='年龄')
    # 作者与作者详情的外键字段  一对一
    author_detail = models.OneToOneField(to='AuthorDetail')

    def __str__(self):
        return '作者对象:%s' % self.name


class AuthorDetail(models.Model):
    phone = models.BigIntegerField(verbose_name='手机号')
    addr = models.CharField(max_length=64, verbose_name='住址')

    def __str__(self):
        return '作者详情:%s' % self.addr

外键字段操作

一对多、一对一外键字段操作

增		
    publish_id=1	  author_detail_id=1
    publish=publish_obj	  author_detail=detail_obj
方法1.
    外键所在的表会生成一个'关联字段_id'的字段 
    '关联字段_id'字段=对应的值 这个对应值也就是关联表的主键值
方法2.
    先取出对象 让'关联字段=对象' 

1.models.Book.objects.create(title='我在南阳种菜的日子', price=1000.22, publish_id=1)

2.publish_obj = models.Publish.objects.filter(pk=2).first()
  models.Book.objects.create(title='七进七出救痴儿', price=5000.66, publish=publish_obj)
改
    update(publish_id=3)	 update(author_detail_id=3)
    update(publish=publish_obj)  update(author_detail=detail_obj)
1.models.Book.objects.filter(pk=1).update(publish_id=2)

2.publish_obj = models.Publish.objects.filter(pk=1).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()
    	括号内无需传值 直接清空当前表在第三张关系表中的绑定记录
# 添加关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.add(1)  # 在第三张关系表中添加数据
    book_obj.authors.add(1, 2)  # 可以直接填写数据主键值
    
    author_obj1 = models.Author.objects.filter(pk=1).first()
    author_obj2 = models.Author.objects.filter(pk=2).first()
    book_obj.authors.add(author_obj1)	# 也可以添加对象
    book_obj.authors.add(author_obj1,author_obj2)
    
# 修改关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.set([3, ])
    book_obj.authors.set([1, 2])
    
    author_obj1 = models.Author.objects.filter(pk=3).first()
    author_obj2 = models.Author.objects.filter(pk=4).first()
    book_obj.authors.set([author_obj1, ])
    book_obj.authors.set([author_obj1, author_obj2])
    
# 移除关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.remove(3)
    book_obj.authors.remove(3,4)
    
    author_obj1 = models.Author.objects.filter(pk=1).first()
    author_obj2 = models.Author.objects.filter(pk=2).first()
    book_obj.authors.remove(author_obj1)
    book_obj.authors.remove(author_obj1,author_obj2)
    
# 清空关系
    book_obj = models.Book.objects.filter(pk=1).first()
    book_obj.authors.clear()

多表查询

"""
MySQL多表查询思路
	子查询
		将SQL语句用括号括起来当做条件使用
	连表操作
		inner join\left join\right join\union
django orm本质还是使用的上述两种方法
	子查询>>>:基于对象的跨表查询
	连表操作>>>:基于双下划线的跨表查询
"""
# 正反向的概念
	核心在于当前数据对象是否含有外键字段 有则是正向 没有则是反向
	正向
  	eg:
      由书籍查询出版社 外键字段在书籍表中 那么书查出版社就是'正向'
      由书籍查询作者 外键字段在书籍表中 那么书查作者就是'正向'
      由作者查询作者详情 外键字段在作者表中 那么也是'正向'
  反向
  	eg:
      由出版社查询书籍 外键字段不在出版社表 那么出版社查书就是'反向'
      ...
        
"""
查询口诀
 	正向查询按外键字段名
 	反向查询按表名小写
"""

基于对象的跨表查询

"""基于对象的跨表查询本质就是子查询 即分步操作即可"""

# 正向查询	从条件所在表出发获取对象
	'obj.关联字段.字段'

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
    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()
    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: 书籍对象:golang高并发>, <Book: 书籍对象:python全栈开发>]>
    
6.查询电话是110的作者
    author_detail_obj = models.AuthorDetail.objects.filter(phone=110).first()
    res = author_detail_obj.author
    print(res)  # 作者对象:jason

基于双下划线的跨表查询

"""基于双下划线的跨表查询本质就是连表操作"""
'''手上有什么条件就先拿models点该条件对应的表名'''
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}]>
# 连续跨表操作
1.查询python全栈开发对应的作者的手机号
	res = models.Book.objects.filter(title='python全栈开发').values('authors__author_detail__phone')
	print(res)  # <QuerySet [{'authors__author_detail__phone': 110}, {'authors__author_detail__phone': 140}]>
    
    res1 = models.AuthorDetail.objects.filter(author__book__title='python全栈开发').values('phone')
	print(res1)  # <QuerySet [{'phone': 110}, {'phone': 140}]>

总结

对象查找(跨表)

1.正向
	对象.关联字段.字段
    	先从表1获取对象1 
    	对象1.关联字段就能拿到关联表表2的对象2
    	再通过对象2.字段即可得关联表表2的对应字段
        
author_obj = models.Author.objects.filter(pk=3).first()
    print(author_obj)	# 表1对象
    print(author_obj.author_detail)	# 表1对象对应的表2对象
    print(author_obj.author_detail.phone)      # 表2对象对应的字段值	
2.反向
	对象.小写表名
    	先从没有外键的表2获取对象2
        通过对象2.小写表名   获取到表1中对应的对象1
# 结果只有一个     一对一关系   
author_detail_obj = models.AuthorDetail.objects.filter(pk=3).first()
print(author_detail_obj)	# 表2对象
author = author_detail_obj.author
print(author)        # 表1对象
 
# 结果有多个		一对多关系	对象.小写表名_set.all()
publish_obj = models.Publish.objects.filter(pk=1).first()
print(publish_obj)	# 表2对象
book_obj = publish_obj.book_set
print(book_obj)		# app01.Book.None
print(book_obj.all())	# QuerySet
'基于对象的反向查询结果可以有多个时 必须加_set.all()'

字段查找(跨表)

1.正向
	关联字段__字段
    
res = models.Author.objects.filter(pk=3).values('author_detail__phone')
    						'author_detail 为关联字段'
    						'phone为字段'
2.反向
	小写表名__字段

res = models.Publish.objects.filter(pk=1).values('book__title')
    print(res)    
# 反向查询的字段查询进阶
1.查询条件字段在从表中
models.Publish.objects.filter(book__title='美羊羊与灰太狼').values()

2.查询字段值在从表中
models.Publish.objects.filter(pk=1).values('book__title')

'''
主从表
	主表:其中存在主键(primary key)用于与其它表相关联
	从表:以主表的主键(primary key)值为外键 (Foreign Key)的表,可以通过外键与主表进行关联查询
	即 含Foreign key的为从表
'''

如何查看SQL语句

方式1:如果结果集对象是queryset 那么可以直接点query查看
方式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',
        },
    }
}
posted @   扶我上码  阅读(99)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示