day 53
day 53 模型层
01.ORM查询
-
在后端直接对models层进行测试
-
方式一:直接使用应用下的tests.py文件
# 去manage.py拷贝前四行代码 # 自己再书写两行就行了 import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings") import django django.setup() # 一定要等待测试脚本搭建完毕之后 才能导入django文件进行测试 from app01 import models
-
方式二:自己新建一个py文件内部也写上方式一的代码
-
-
单表操作
-
创建数据
-
create方法
book_obj = models.Books.objects.create(title='三国演义',price=123.23,publish_date='2019-11-11') # 日期格式可以接收字符串,还可以传日期对象 from datetime import date ctime = date.today() book_obj = models.Books.objects.create(title='红楼梦', price=888.99, publish_date=ctime)
-
利用对象的绑定方法save
book_obj = models.Books(title='西游记',price=666.66,publish_date='2000-1-21') book_obj.save()
-
-
修改数据
-
利用queryset对象的update方法
res = models.AuthorDetail.objects.filter(id=4).update(phone=121212)
# 只要是queryset对象就可以无限制的调用queryset方法 res = models.Books.objects.filter(pk=1).filter().filter().filter().filter() # 只要是queryset对象都可以.query查看当前结果对应的sql语句 res.query SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1
-
对象.字段=修改值(会将对象的所有字段都修改一遍,不推荐使用)
obj = models.Author.objects.filter(id=2).first() obj.age=24 obj.save()
-
-
删除数据
-
利用queryset对象的delete方法
models.Books.objects.filter(pk=3).delete()
-
对象.delete()
book_obj = models.Books.objects.get(pk=3) book_obj.delete()
get和filter区别 1.filter获取到的是一个queryset对象 类似于一个列表 2.get获取到的直接就是数据对象本身 当条件不存在的情况下 filter不报错直接返回一个空 推荐使用filter方法 get直接报错 所以不推荐使用get方法
-
-
查询数据
orm语句的默认都是惰性查询
只有当真正使用数据时才会执行sql语句
-
all(): 查询所有结果(返回queryset对象)
res = models.Books.objects.all()
-
filter(**kwargs): 它包含了与所给筛选条件相匹配的对象(相当于sql语句中的where)(返回queryset对象)
res = models.Books.objects.filter(pk=1,title='三') # 支持多个参数 并且是and关系
-
get(**kwargs): 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。(不推荐使用)
res = models.Books.objects.get(title='西游记') res1 = models.Books.objects.filter(title='西游记')
-
first(): 返回queryset中的第一个对象,返回结果为数据对象
res = models.Books.objects.filter(title='西游记').first()
-
last(): 返回queryset中的最后一个对象,返回结果为数据对象
res = models.Books.objects.filter(title='西游记').last()
-
count(): 统计queryset中数据的个数,返回数字int
num = models.Books.objects.count()
-
values(*field): 获取数据对象中指定的字段值,可以有多个(返回一个ValueQuerySet——一个特殊的QuerySet(列表套字典),运行后得到的并不是一系列model的实例化对象,而是一个可迭代的字典序列)
res = models.Books.objects.values('title','price') <QuerySet [{'title': '三国演义', 'price': Decimal('222.66')}, {'title': '红楼梦', 'price': Decimal('888.99')}, {'title': '西游记', 'price': Decimal('444.66')}, {'title': '西游记', 'price': Decimal('666.22')}]>
-
values_list(*field): 它与values()非常相似,它返回的是一个元组序列(列表套元组),values返回的是一个字典序列
res = models.Books.objects.values_list('title','price') <QuerySet [('三国演义', Decimal('222.66')), ('红楼梦', Decimal('888.99')), ('西游记', Decimal('444.66')), ('西游记', Decimal('666.22'))]>
-
order_by(*field): 对查询结果,按照指定的字段排序(默认升序)
res = models.Books.objects.order_by('price') # 默认是升序 res1 = models.Books.objects.all().order_by('price') # 默认是升序 两者等价 下面的方式 语义更明确
-
reverse(): 对查询结果反向排序,请注意reverse()通常只能在具有已定义顺序的QuerySet上调用(在model类的Meta中指定ordering或调用order_by()方法)。
res = models.Books.objects.all().order_by('price').reverse() res1 = models.Books.objects.all().order_by('-price') # 也是降序效果
-
exclude(**kwargs): 它包含了与所给筛选条件不匹配的对象(排除符合条件的数据)
res = models.Books.objects.all().exclude(title='三国演义')
-
exists(): 如果QuerySet包含数据,就返回True,否则返回False
res = models.Books.objects.filter(pk=1).exists() # 该方法其实不需要使用 因为数据本身自带布尔值
-
distinct(): 从返回结果中剔除重复纪录(如果你查询跨越多个表,可能在计算QuerySet时得到重复的结果。此时可以使用distinct(),注意只有在PostgreSQL中支持按字段去重。)(数据必须要是完全相同的,包括主键)
res = models.Books.objects.values('title','price').distinct()
-
-
如果想要查看所有的sql语句
# 放在settings.py中 # 在涉及到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', }, } }
-
-
双下划线查询
-
大于,小于,大于等于,小于等于
查询价格大于500的书籍 res = models.Books.objects.filter(price__gt=500) 查询价格小于400 的书籍 res = models.Books.objects.filter(price__lt=400) 查询价格大于等于500 res = models.Books.objects.filter(price__gte=500) 查询价格小于等于500的书籍 res = models.Books.objects.filter(price__lte=500)
-
是a或b或c
# 查询价格是222.66或者444.22或者500的书籍 res = models.Books.objects.filter(price__in=[222,444,500])
-
范围查询
# 查询价格在200到800之间的书籍 res = models.Books.objects.filter(price__range=(200,800)) # 顾头顾尾
-
日期查询
# 查询出版日期是2019年的书籍 res = models.Books.objects.filter(publish_date__year='2019') # 查询出版日期是1月份的书籍 res = models.Books.objects.filter(publish_date__month='1')
-
模糊查询
""" MySQL中的模糊查询 关键字 like 模糊匹配的符号 %:匹配任何个数的任意字符 _:匹配一位任意的字符 """
# 查询书籍是以三开头的书 res = models.Books.objects.filter(title__startswith='三') # 查询书籍是以义结尾的书 res = models.Books.objects.filter(title__endswith='1') # 查询书籍名称中包含游字的书籍 res = models.Books.objects.filter(title__contains='游') # 查询书籍名称中包含字母p的书籍 res = models.Books.objects.filter(title__contains='p') # 默认区分大小写 res = models.Books.objects.filter(title__icontains='p') # 忽略大小写 加i
-
-
图书管理表设计
- auto_now 和 auto_now_add
-
(一对多)外键字段的增删改查
-
增
models.Book.objects.create(title='三国演义',price=222.33,publish_id=1)
publish_obj = models.Publish.objects.filter(pk=2).first() models.Book.objects.create(title='红楼梦',price=444.33,publish=publish_obj) # models中的外键字段接收关联对象,自动将pk主键值绑定
-
删
models.Publish.objects.filter(pk=1).delete() # 默认就是级联删除 级联更新 # 会自动将关联数据全部删除
-
改
# 第一种 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)
-
查
-
-
(多对多)外键字段的增删改查(第三张表)
-
增
- add
book_obj = models.Book.objects.filter(pk=2).first() # 点外键字段 可能会直接获取到外键关联的数据对象 book_obj.authors.add(1,2) # 在第三张表里面给书籍绑定一个主键为1,2的作者
author_obj = models.Author.objects.filter(pk=1).first() author_obj1 = models.Author.objects.filter(pk=2).first() book_obj.authors.add(author_obj,author_obj1) # 该方法也可以传对象
-
删
-
remoeve 既可以传数字 也可以穿对象,并且都支持传多个 不需要迭代
book_obj = models.Book.objects.filter(pk=2).first() 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,author_obj1)
-
clear clear清空书籍相关所有记录 括号内不需要传递参数
book_obj = models.Book.objects.filter(pk=2).first() book_obj.authors.clear()
-
-
改
- set (内部放可迭代对象)
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))
-
查
-
-
跨表查询
-
子查询,基于对象
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()
3.查询作者是jason的手机号码 author_obj = models.Author.objects.filter(name='jason').first() print(author_obj.author_detail) print(author_obj.author_detail.phone)
-
联表查询(基于双下划线)
# 正向 res = models.Book.objects.filter(pk=2).values('publish__name') # 写外键字段就相当于已经跨到外键字段所关联的表 # 你想要改表的哪个字段信息 你只需要加__获取即可 # 反向 res = models.Publish.objects.filter(book__pk=2).values('name') # 还是在models.的表中
-
-
聚合查询