Django ORM语法进阶

Django ORM语法进阶

单表操作

  • 在操作前可以先配置好测试环境,方便对数据库进行测试
1. 在tests.py文件中写入下面代码 (任意新建一个文件也行)

import os


if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djangoProject.settings")
    import django
    django.setup()
    
    # 所有的代码都必须等待环境准备完毕之后才能书写
    from app01 import models
    models.User.objects.all()
  • django自带的sqlite3数据库对日期格式不是很敏感 处理的时候容易出错,所以我们用mysql数据库
ORM创建时间日期代码有
	models.DateFiled()
    models.DateTimeFiled()
    
    
参数解析:
	auto_now : 每次操作数据的时候,该字段会自动更新当前时间
    auto_now_add : 创建数据的时候,会自动将当前时间记录下来,只有人为修改才会改变
方式1:
	res = models.表名.objects.create(字段名1=1,字段名2=2,...)
    
方式2:
	res = models.表名(字段名1=1,字段名2=2,...)
    res.save()
res = models.表名.objects.filter(字段名=).delete()
建议使用
res = models.表名.objects.filter(pk=).delete()
	pk会自动查找当前表的主键字段 指代的就是当前表的主键字段  值为主键字段的值
    res 返回值返回的是你删除的表名和删除了几行
方式1:
res = models.表名.objects.filter(字段名=).updata(字段名1=1,字段名2=2,...)
方式2:
res = models.表名.objects.get(字段名=) 
res.字段名1 =1
res.字段名2 =2
res.save()
'''
	get方法返回的值就是当前数据对象
	由于一旦数据不存在该方法会直接报错,而filter则不会,不推荐使用get
'''

在这里插入图片描述

必知必会13条

参数解析
all()查询所有数据
filter()带有过滤条件查询
get()直接拿数据对象 但是条件不存在就直接报错
first()拿第一个
last()拿最后一个
values()获取值,可以指定字段
values_list()获取值,可以指定字段 数据格式同上面不一样
distinct()去重
order_by(‘age’)排序,默认升序,加(-):(‘-age’)就降序
reverse()反转,前提是数据已经排过序
count()统计当前数据个数
exclude()排除在外
exists()判断是否存在,返回值是布尔值

查看内部sql语句的方式

# 方式1
res = models.User.objects.values_list('name','age')  # <QuerySet [('jason', 18), ('egonPPP', 84)]>
print(res.query)
只有queryset对象才能够点击query查看内部的sql语句

# 方式2:所有的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',
        },
    }
}

神奇的双下划线查询

1. __gt 大于
	# 年龄大于35岁的数据
	res = models.User.objects.filter(age__gt=35)
2. __lt 小于
	 # 年龄小于35岁的数据
	res = models.User.objects.filter(age__lt=35)
3. __gte 大于等于  __lte 小于等于
4. __in 存在
	# 年龄是18 或者 32 或者40
    res = models.User.objects.filter(age__in=[18,32,40])
5. __range
	# 年龄在18到40岁之间的  首尾都要
    res = models.User.objects.filter(age__range=[18,40])
6. __contains  # 模糊查询
	# 查询出名字里面含有s的数据  模糊查询  忽略大小写
    res = models.User.objects.filter(name__contains='s')
7. __icontains  # 忽略大小写
	res = models.User.objects.filter(name__icontains='p')
8. __startswith 和 __endswith  以某某开头和以某某结尾

9. __month,__year,__day...  
	获取月份 年份  天 ...
	# 查询出注册时间是 2020 1月
    # res = models.User.objects.filter(register_time__month='1')
    # res = models.User.objects.filter(register_time__year='2020')

在这里插入图片描述

一对多外键增删查改

1 直接写实际字段  publish_id = id
	model.Book.objects.create(title='论语',price=899.23,publish_id=1)
2 虚拟字段  publish_id = 对象
	publish_obj = models.Publish.objects.filter(pk=2).first()
    models.Book.objects.create(title='红楼梦',price=666.23,publish=publish_obj	
models.Publish.objects.filter(pk=1).delete()  # 级联删除
  1. 修改
models.Book.objects.filter(pk=1).update(publish_id=2)  # publish_id也可以对象

多对多外键增删查改

  • 多对多外键关系会自动建立第三张表,而在orm中是无法直接通过 点 的方式点到第三张表,多对多需要先进行如下操作
1. 先获取对象
	book_obj = models.Book.objects.filter(pk=1).first()
2. 通过  author = models.ManyToManyField('Author') 来获取第三张表
	book_obj.author
  1. 增.add
book_obj.author.add(1,2)  # 书籍id为1的书籍绑定主键为1 和 2 的作者 
author_obj1 = models.Author.objects.filter(pk=2).first()
book_obj.authors.add(author_obj) 
 """
    add给第三张关系表添加数据
        括号内既可以传数字也可以传对象 并且都支持多个
"""
  1. 删.remove
book_obj.authors.remove(2)
"""
    remove
        括号内既可以传数字也可以传对象 并且都支持多个
"""
  1. 修改
book_obj.authors.set([1,2])  # 括号内必须给一个可迭代对象
book_obj.authors.set([author_obj,author_obj1])  # 括号内必须给一个可迭代对象
"""
	set
		括号内必须传一个可迭代对象,该对象内既可以数字也可以对象 并且都支持多个
"""
  1. 清空
book_obj.authors.clear()  #  不需要任何参数  会清空第三张关系表中某个书籍与作者的绑定关系

在这里插入图片描述

正反向概念

外键字段在手上那么,通过外键查另一种表数据就是正向

外键字段如果不在手上,通过外键查另一种表数就是反向

正向查询按字段

反向查询按表名小写

多表查询案例

子查询(基于对象的跨表查询)

  1. 查询书籍主键为1的出版社
book_obj = models.Book.objects.filter(pk=1).first()
res = book_obj.publish
print(res)
# 正向查询
  1. 查询书籍主键为2的作者
book_obj = models.Book.objects.filter(pk=2).first()
res = book_obj.author  # app01.Author.None
print(res.all())   # <QuerySet [<Author: Author object>]>
# 正向查询
  1. 查询作者张三的电话号码
author_obj = models.Author.objects.filter(name='张三').first()
res = author_obj.author_detail.iphone
print(res)  
# 正向查询
  1. 查询出版社是东方出版社的书
publish_obj = models.Publish.objects.filter(name='东方出版社').all()
res = publish_obj.book_set  # app01.Book.None
print(res.all())   # <QuerySet [<Book: Book object>]>
# 反向查询
  1. 查询作者是李四写过的书
author_obj = models.Author.objects.filter(name='李四').first()
res = author_obj.book_set
print(res.all())
# 反向查询
  1. 查询手机号是 110 的作者姓名
author_d_obj = models.AuthorDetail.objects.filter(iphone=110).first()
res = author_d_obj.author
print(res.name)
# 反向查询

总结:

正向查询时

  • 当结果可能由多个的时候需要加.all()
  • 当结果是一个的时候直接拿到数据对象

反向查询时

  • 当查询结果可以有多个的时候 必须要加上_set.all()
  • 当结果只有一个的时候 不需要加_set.all()
    在这里插入图片描述

联表查询(基于双下划线的跨表查询)

使用.values 和 .values_list 联表查询。 默认是全联表,不能为空。只会查询外键字段有值的数据,不会查询外键字段为空的数据。
解决方案: 在 orm 里面加上 null=true,查询就会变成左联表

  1. 查询张三的手机号
res = models.Author.objects.filter(name='张三').values('author_detail__iphone')
print(res)  # <QuerySet [{'author_detail__iphone': 123456789098}]>
# 正向
res = models.AuthorDetail.objects.filter(author__name='张三').values('iphone')
print(res)
# 反向
  1. 查询书籍主键为1的出版社名称和书的名称
res = models.Book.objects.filter(pk=1).values('name','publish__name')
print(res)  <QuerySet [{'name': '论语', 'publish__name': '东方出版社'}]>
# 正向
res = models.Publish.objects.filter(book__id=1).values('book__name','name')
print(res)
# 反向
  1. 查询书籍主键为1的作者姓名
res = models.Book.objects.filter(pk=1).values('author__name')
print(res)
# 正向
res = models.Author.objects.filter(book__id=1).values('name')
print(res)
# 反向
  1. 查询书籍主键是1的作者的手机号
res = models.Book.objects.filter(pk=1).values('author__author_detail__iphone')
print(res)
# 正向
res = models.AuthorDetail.objects.filter(author__book__id=1).values('iphone')
print(res)
# 反向
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

go&Python

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值