ICode9

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

Django---外键创建,表查询

2022-05-18 00:32:06  阅读:152  来源: 互联网

标签:__ filter models res 外键 Django --- objects 查询


双下划线查询


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',
        },
    }
}

标签:__,filter,models,res,外键,Django,---,objects,查询
来源: https://www.cnblogs.com/zaoan1207/p/16283046.html

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

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

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

ICode9版权所有