目录
配置测试脚本
当你想单独测试django中某一个py文件,需要手动配置测试脚本
#在manage.py中拷贝前四行代码,可以直接写在应用名下的test.py中 import os if __name__ == '__main__': os.environ.setdefault('DJANGO_SETTINGS_MODULE','day55.seetings') import django django.setup() from app01 import models
ORM普通查询
创建数据
create
#字段值可以是对象 obj = models.Table.objects.create(key=value,)
对象绑定方法
obj = models.Table(key=value,) obj.save()
修改数据
Queryset方法
#py会自动查找到当前表的主键字段 models.Table.objects.filter(pk=1).update(key=value,)
filter查询出来的结果都是一个Queryset对象
只要是queryset对象就可以无限制的调用queryset方法
只要是queryset对象就可以.query查看当前结果内部对应的sql语句
res = models.Table.objects.filter(pk=1) print(res.query)
对象方法
#不推荐使用,利用对象的修改,实质是重写记录的所有字段,效率低 book_obj = models.Books.objects.get(pk=1) book_obj.price = 222.66 book_obj.save()
get和filter的区别
- filter获取到的是一个Queryset对象,类似于一个列表
- get获取到的是数据对象本身
- 当条件不存在的情况下,filter返回空,get直接报错
删除数据
queryset方法
models.Table.objects.filter(pk=1).delete()
对象方法
obj = models.Table.objects.get(pk=1) obj.delete()
查找数据
orm语句的查询默认都是惰性查询,只有真正要使用数据的时候才会执行orm语句
夺命13条
# all() 查询所有 返回Queryset对象 res = models.Table.objects.all()
# filter() 筛选 相当于sql中的where关键字 res = models.Table.objects.filter(pk=1,)
# get() 筛选 获取到的是对象本身 条件不存在直接报错 res = models.Table.objects.get(title='西游记',)
# first() 取queryset中的第一个数据对象 res = models.Books.objects.filter(title='西游记').first()
# last() 取queryset中的最后一个数据对象 res = models.Books.objects.filter(title='西游记').last()
# count() 统计数据的个数 数字 num = models.Books.objects.count() print(type(num))
# values() 获取数据对象中指定的字段的值 返回queryset对象 列表套字典 res = models.Books.objects.values('title','price') print(res) # <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}, {'title': '西游记', 'price': Decimal('444.66')}, {'title': '西游记', 'price': Decimal('666.22')}]>
# values_list() 获取数据对象中指定的字段的值 返回queryset对象 列表套元祖 res = models.Books.objects.values_list('title','price') print(res) #<QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
# order_by() 按照指定的字段排序 res = models.Books.objects.order_by('price') # 默认是升序 res1 = models.Books.objects.all().order_by('price') # 默认是升序 两者等价 下面的方式 语义更明确 # 降序 字段前面加负号 res1 = models.Books.objects.all().order_by('-price') print(res1)
# reverse() 颠倒顺序 前提是跌倒的对象必须有顺序(提前排序之后才能跌倒) res = models.Books.objects.all() res1 = models.Books.objects.all().reverse() res2 = models.Books.objects.all().order_by('price') res3 = models.Books.objects.all().order_by('price').reverse() print(res2,res3)
# exclude() 排除什么什么之外 queryset对象 res = models.Books.objects.all().exclude(title='三国演义') print(res) <QuerySet [<Books: 红楼梦>, <Books: 西游记1>, <Books: 西游记2>]>
# exists() 判断查询结果是否有值 返回结果是一个布尔值 鸡肋 res = models.Books.objects.filter(pk=1).exists() print(res)
# distinct() 对查询结果进行去重操作 去重的前提:数据必须是完全想要的情况下 才能# 够去重(容易忽略主键),多和values()连用 res = models.Books.objects.values('title','price') res = models.Books.objects.values('title','price').distinct() print(res)
#values和values_list # 查询价格小于400 的书籍 res = models.Book.objects.filter(price__lt=400).values_list() res1 = models.Book.objects.filter(price__lt=400).values() print(res) print(res1) ''' <QuerySet [(4, '西游记', Decimal('333.00'), datetime.date(2019, 10, 29), 3)]> <QuerySet [{'id': 4, 'title': '西游记', 'price': Decimal('333.00'), 'publish_date': datetime.date(2019, 10, 29), 'publish_id': 3}]> '''
双下划线查询
# modls.py from django.db import models # Create your models here. class Books(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) publish_date = models.DateField() def __str__(self): return self.title # 表查询 以图书管理系统为例 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8,decimal_places=2) publish_date = models.DateField(auto_now_add=True) """ auto_now:每次修改的数据的时候 都会自动更新修改书籍(展示最新的一次修改时间) auto_now_add:当数据创建出来的时候 会自动将创建时间记录下来 """ publish = models.ForeignKey(to='Publish') authors = models.ManyToManyField(to='Author') class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=64) def __str__(self): return self.name class Author(models.Model): name = models.CharField(max_length=32) email = models.EmailField() # 对应到数据库中仅仅是varchar(254) 没有任何的限制条件 该字段只要是字符串就可以 # 仅仅是为了表达语义 如何限制 后期需要借助于校验性组件 author_detail = models.OneToOneField(to='AuthorDetail') def __str__(self): return self.name class AuthorDetail(models.Model): phone = models.BigIntegerField() addr = models.CharField(max_length=64) def __str__(self): return self.addr
# test.py 查询脚本 # 查询价格大于500的书籍 # res = models.Books.objects.filter(price__gt=500).value_list() # print(res) # 查询价格小于400 的书籍 # res = models.Books.objects.filter(price__lt=400) # print(res) # 查询价格大于等于500 # res = models.Books.objects.filter(price__gte=444.66) 对数字精确度不敏感 # res = models.Books.objects.filter(price__gte=500) # print(res) # 查询价格小于等于500的书籍 # res = models.Books.objects.filter(price__lte=500) # print(res) # 查询价格是222.66或者444.22或者500的书籍 # res = models.Books.objects.filter(price__in=[222,444,500]) # print(res) # 查询价格在200到800之间的书籍 # res = models.Books.objects.filter(price__range=(200,800)) # 顾头顾尾 # print(res) # 查询出版日期是2019年的书籍 # res = models.Books.objects.filter(publish_date__year='2019') # print(res) # 查询出版日期是1月份的书籍 # res = models.Books.objects.filter(publish_date__month='1') # print(res) # 模糊查询 """ MySQL中的模糊查询 关键字 like 模糊匹配的符号 %:匹配任何个数的任意字符 _:匹配一位任意的字符 """ # 查询书籍是以三开头的书 # res = models.Books.objects.filter(title__startswith='三') # print(res) # 查询书籍是以义结尾的书 # res = models.Books.objects.filter(title__endswith='1') # print(res) # 查询书籍名称中包含游字的书籍 # res = models.Books.objects.filter(title__contains='游') # print(res) # 查询书籍名称中包含字母p的书籍 # res = models.Books.objects.filter(title__contains='p') # 默认区分大小写 # res = models.Books.objects.filter(title__icontains='p') # 忽略大小写 加i # print(res) # 一对多字段数据的增删改查 # 增 # 第一种 # models.Book.objects.create(title='三国演义',price=222.33,publish_id=1) # 直接传表里面的实际字段 跟数据主键值 publish_id # 第二种 # publish_obj = models.Publish.objects.filter(pk=2).first() # models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj) # 传虚拟字段 跟数据对象即可 # 查 # 改 # 第一种 # models.Book.objects.filter(pk=1).update(publish_id=2) # 第二种 # publish_obj = models.Publish.objects.filter(pk=1).first() # models.Book.objects.filter(pk=1).update(publish=publish_obj) # 删 # models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新 # 多对多字段数据的增删改查 # 增 # book_obj = models.Book.objects.filter(pk=2).first() # print(book_obj.publish) # 点外键字段 可能会直接获取到外键关联的数据对象 # 给当前这一本书绑定作者 # 麻瓜做法 自己直接去操作第三张表 # print(book_obj.authors) # 已经跨到第三张表了 # book_obj.authors.add(1) # 在第三张表里面给书籍绑定一个主键为1的作者 # book_obj.authors.add(1,2) # 在第三张表里面给书籍绑定一个主键为1的作者 # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # # book_obj.authors.add(author_obj) # book_obj.authors.add(author_obj,author_obj1) """ add方法 能够朝第三张关系表添加数据 即支持传数字 add(1,2) 也支持传对象 add(author_obj,author_obj1) 并且两者都可以是多个 """ # 改 # book_obj = models.Book.objects.filter(pk=2).first() # # book_obj.authors.set((1,3)) # # book_obj.authors.set([1,]) # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # book_obj.authors.set((author_obj,author_obj1)) """ set修改多对多关系表中的数据 既可以传数字也可以传对象 但是需要注意的是括号内必须是可迭代对象 都支持多个 set((1,3)) set((author_obj,author_obj1)) """ # 删 # book_obj = models.Book.objects.filter(pk=2).first() # book_obj.authors.remove(100) # book_obj.authors.remove(1,2) # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # # book_obj.authors.remove(author_obj) # book_obj.authors.remove(author_obj,author_obj1) """ remove既可以传数字 也可以穿对象 并且都支持传多个 不需要迭代 remove(1,2) remove(author_obj,author_obj1) """ # 清空 删除某个数据在第三张表中的所有记录 # book_obj = models.Book.objects.filter(pk=2).first() # book_obj.authors.clear() """ clear清空书籍相关所有记录 括号内不需要传递参数 """ # 跨表查询(******) """ 正反向查询 关系字段在谁哪 由谁查谁就是正向 如果关系字段 就是反向 正向查询按字段 反向查询按表名小写 + _set """ # 基于对象的跨表查询 子查询 分步操作 # 1.查询书籍主键为2的出版社名称 # book_obj = models.Book.objects.filter(pk=2).first() # print(book_obj.publish) # 出版社对象 # print(book_obj.publish.name) # 2.查询书籍主键为4的作者姓名 # book_obj = models.Book.objects.filter(pk=4).first() # print(book_obj.authors) # app01.Author.None # print(book_obj.authors.all()) # 3.查询作者是jason的手机号码 # author_obj = models.Author.objects.filter(name='jason').first() # print(author_obj.author_detail) # print(author_obj.author_detail.phone) """ 什么时候需要加all 当正向查询点击外键字段数据有多个的情况下 需要.all() app01.Author.None 一旦看到该结果 只需要加.all()即可 在写orm语句的时候跟你写sql语句一样 不要想着一次性写完 写一点查一点再写一点 """ # 4.查询出版社是东方出版社出版过的书籍 # publish_obj = models.Publish.objects.filter(name='东方出版社').first() # # print(publish_obj.book_set) # app01.Book.None # print(publish_obj.book_set.all()) # 5.查询作者是jason写过的书籍 # author_obj = models.Author.objects.filter(name='jason').first() # # print(author_obj.book_set) # app01.Book.None # print(author_obj.book_set.all()) # app01.Book.None # 6.查询手机号是120的作者姓名 # author_detail_obj = models.AuthorDetail.objects.filter(phone=120).first() # print(author_detail_obj.author) # print(author_detail_obj.author.email) """ 什么时候反向查询的时候表名小写需要加_set 一对多 多对多 一对一不需要加_set """ # 基于双下滑线的跨表查询 联表操作 """ inner join left join right join union """ # 1.查询书籍pk为2的出版社名称 # 正向 # res = models.Book.objects.filter(pk=2).values('publish__name') # 写外键字段就相当于已经跨到外键字段所关联的表 # 你想要改表的哪个字段信息 你只需要加__获取即可 # print(res) # 反向 # res = models.Publish.objects.filter(book__pk=2).values('name') # print(res) # 2.查询书籍pk为2的作者姓名和邮箱 # res = models.Book.objects.filter(pk=2).values('authors__name','authors__email') # print(res) # res = models.Author.objects.filter(book__pk=2).values('name','email') # print(res) """ models后面点的谁 就以谁为基表 """ # 3.查询作者是egon的家庭地址 # res = models.Author.objects.filter(name='egon').values('author_detail__addr') # print(res) # res = models.AuthorDetail.objects.filter(author__name='egon').values('addr') # print(res) # 4.查询出版社是东方出版社出版过的书的名字 # res = models.Publish.objects.filter(name='东方出版社').values('book__title') # print(res) # res = models.Book.objects.filter(publish__name='东方出版社').values('title') # print(res) # 查询书籍pk是2的作者的手机号 # res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone') # print(res) # res = models.Author.objects.filter(book__pk=2).values('author_detail__phone') # print(res)
大于/小于
filed__gt = xxx filed__lt = xxx
大于等于/小于等于
#对数字精确度不敏感 filed__gte = xxx filed__lte = xxx
或
field__in=[x,y,z]
之间
filed__range(x,y) # 包含x,y
模糊查询
以。。。开头
field__startswith='xxx'
以。。。结尾
field__endswith = 'xxx'
包含。。。
field__contains = 'xxx' # 默认区分大小写 field__icontains = 'xxx' # 忽略大小写
一对多字段数据的操作
增/改:可以直接出传实际字段的值,虚拟字段传对象
删:
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新
多对多字数数据的操作
增:
book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.publish) # 点外键字段 可能会直接获取到外键关联的数据对象 book_obj.authors.add(1,) # 在第三张表里面给书籍绑定一个主键为1的作者,可多个 author_obj = models.Author.objects.filter(pk=1).first() book_obj.authors.add(author_obj) # add也支持传对象
改:
book_obj = models.Book.objects.filter(pk=2).first() #set会删除authors中所有book_obj的记录,并重新添加 book_obj.authors.set((1,3)) #支持传对象 # author_obj = models.Author.objects.filter(pk=1).first() # author_obj1 = models.Author.objects.filter(pk=2).first() # book_obj.authors.set((author_obj,author_obj1))
删:
book_obj = models.Book.objects.filter(pk=2).first() book_obj.authors.remove(1,) author_obj = models.Author.objects.filter(pk=1).first() book_obj.authors.remove(author_obj)
清空:
# 清空 删除某个数据在第三张表中的所有记录 book_obj = models.Book.objects.filter(pk=2).first() book_obj.authors.clear()
跨表查询
正向查询:包含关系字段的表,查关联表;按字段查询
反向查询,不含关系字段的表,查关联表;按表名小写_set
正向查询
子查询
# 1.查询书籍主键为2的出版社名称,通过.外键字段可以获取对象 book_obj = models.Book.objects.filter(pk=2).first() print(book_obj.publish) # 出版社对象 print(book_obj.publish.name)
# 2.查询书籍主键为4的作者姓名 book_obj = models.Book.objects.filter(pk=4).first() print(book_obj.authors) # app01.Author.None print(book_obj.authors.all()) # 当查询结果有多个值时,使用all()
反向查询
在一对多和多对多的情况下,使用_ set ;一对一情况下不需要加_ set
基于双下划线的跨表查询
两表
# 1.查询书籍pk为2的出版社名称 # 正向 res = models.Book.objects.filter(pk=2).values('publish__name') # 写外键字段就相当于已经跨到外键字段所关联的表 # 你想要改表的哪个字段信息 你只需要加__获取即可 print(res) # 反向 res1 = models.Publish.objects.filter(book__pk=2).values('name') print(res1)
多表
# 查询书籍pk是2的作者的手机号 res = models.Book.objects.filter(pk=2).values('authors__author_detail__phone') print(res) #可以有不同的基准 res1 = models.Author.objects.filter(book__pk=2).values('author_detail__phone') print(res1)