ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

django之神奇的双下划线查询 orm创建外键关系 外键字段的增删查改 正反向的概念 models文件 基于对象的跨表查询 基于双下划线的跨表查询 双下线查询扩展

2022-06-15 21:01:34  阅读:135  来源: 互联网

标签:__ 下划线 models res 查询 filter 跨表 objects


概要

  • 神奇的双下划线查询
  • orm创建外键关系
  • 外键字段的增删查改
  • 正反向的概念
  • 多表查询

内容

1.双下划线查询

# 1.查询年龄大于20岁的用户
res = models.User.objects.filter(age_gt=20)
print(res)
知识点:
    __gt      大于
    ——lt      小于
    ——gte     大于等于
    ——lte     小于等于
    
# 2.查询年龄是18 22 25 的用户
res = models.User.objects.filter(age_in=[18,22,25])
print(res)
知识点: __in    相当于成员运算 按范围内查找

# 3.查询年龄在18到26之间的用户
res = models.User.objects.filter(age_range=[18,26]) # 必区间 包括18和26
print(res)

知识点:  __range       范围查询

# 4.查询姓名中包含字母j的用户
res = models.User.objects.filter(name_contains='j')

res = models.User.objects.filter(name_icontains='j')
print(res)

知识点:
    __contains    区分大小写
    ——icontains   忽略大小写

# 其他方法补充
知识点:
_startswith      查询以什么开头
_endswith        查询以什么结尾的
_regex    查询某个字段的值是否满足正则表达式的条件

# 6.查询月份是五月的数据
res = models.User.objects.filter(op_time_month=5)
print(res)

查询年份是22年的数据
res = models.User.objects.filter(op_time_year=2022)
print(res)
知识点:
    _year    按照年份筛选数据
    _month   按照月份筛选数据

2.外键字段的创建

MySQL复习

关系的种类:
一对多关系、多对多关系、一对一关系

关系的判断
换位思考  
比如:书与出版社 一本书能不能对应多个出版社 一个出版社能不能对应多本书 看符合哪种关系 到处关系的判断
    
    
针对"在"django"中关系的种类 "

# 1.书与出版社的外键字段:
 书与出版社
 一本书不能对应多个出版社
 一个出版社可以对应多本书
书是多 出版社是一  ==》一对多 ForeignKey

publish = models.ForeignKey(to='Publish')
# 默认关联的就是一对多关系一中的关键字段

"django orm外键字段针对一对多关系也是建在多的一方"

# 2.书与作者的关键字段
书与作者
一本书可以对应多个作者
一个作者可以对应多本书
书是多 作者是多 ==》多对多 ManyToManyField

authors = models.ManyToManyField(to='Author') 
# 自动创建书与作者的第三张关系表

'django orm 外键字段针对多对多关系 可以不用自己创建第三张表'

# 3.作者与作者详情的外键字段
作者与作者详情
一个作者不能对应多个作者详情
一个作者详情不能对应多个作者
作者是一 作者详情是一 ===》一对一 OneToOneField

author_detail = models.OneToOneField(to='AuthorDetail')

"django orm外键字段针对一对一关系 建在查询频率较高的表中"

ps:三个关键字里面的参数  
    to用于指定跟哪张表有关系  自动关联主键
    to_field\to_fields  也可以自己指定关联字段
    
ManyToManyField不会在表中创建实际的字段 而是会告诉django orm自动创建第三张关系表
ForeignKey、OneToOneField 会在字段的后面自动添加_id后缀 如果你在定义模型类的时候自己添加了该后缀那么迁移的时候还会再次添加_id_id 所以不要自己加_id后缀

3.关键字操作

# 一对一、一对多外关键字段操作  
1.增:新增一本书 create
models.Book.objects.create(title='聊斋志异',price=1799.22,publish_id=1)
publish_id=1(可以直播传主键值)

# publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='马可波罗东游记',price=1699.36,publish=publish_obj)
	publish=publish_obj  (可以直接传数据对象)
    
	author_detail_id=1(可以直接写id值)
    author_detail=detail_obj(也可以传数据对象)

2.改
update(publish_id=3)
update(author_detail_id=3)
update(publish=publish_obj)
update(author_detail=detail_obj)

# 多对多字段操作
1.第三张关系表创建数据 add 
book_obj = models.Book.objects.filter(pk=1).first() # 先找到需要创建的那个对象
book_obj.authors.add()  然后通过对象点就可以 括号内可以放主键也可以放数据对象 并且都支持多个

2.第三张关系表修改数据  set
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.author.set([3,])
book_obj.author.set([1,2])

author_obj = models.Author.objects.filter(pk=3).first()
book_obj.authors.set([author_obj1,])
book_obj.authors.set([author_obj1,author_obj2])
括号内必须是一个可迭代(iterable)对象(列表或字典等)元素同样支持主键值或者数据对象

3.第三张关系表删除数据 remove
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.remove(3)
book_obj.authors.remove(3,4)
括号内可以放主键值也可以放数据对象 并且都支持多个

4.第三张关系表清空指定数据 clear
book_obj.authors.clear()
括号内无需传值 直接清空当前表在第三张关系表中的绑定记录

4.多表查询

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

5.models文件

from django.db import models

# create your models here.

# 图书馆
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

6.基于对象的跨表查询

"""基于对象的跨表查询本质就是子查询即分布操作即可"""
# 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

7.基于双下划线的跨表查询

"""基于双下划线的跨表查询本质就是连表查询"""
# 基于双下划线的跨表查询
    """
    查询数据分析书籍对应的价格和出版日期
    models.Book.objects.filter(title='数据分析').values('price','publish_time')
    """
    '''手上有什么条件就先拿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}]>

8.双下线查询扩展

"""基于双下划线的跨表查询的结果也可以是完整的数据对象"""

'''手上有条件所在的表可以不被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}]>
 


# 连续跨表操作
# 查询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}]>


"""
可能出现的不是疑问的疑问:如何获取多张表里面的字段数据
res = models.Book.objects.filter(title='python全栈开发').values('authors__author_detail__phone','authors__name','title')
print(res)
"""

标签:__,下划线,models,res,查询,filter,跨表,objects
来源: https://www.cnblogs.com/wht488232/p/16379786.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有