模型层
如何查询orm语句内部真正的sql语句的两种方式
- 如果是queryset对象,可以直接点query查看
- 配置文件中,直接配置
LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level': 'DEBUG', }, } }
django测试环境的搭建
import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "one_search.settings") import django django.setup() # 写完以上代码就可以在django测试任何的py文件
单表操作
增
方式1:
models.表名.objects.create(键=值,...)
方式2:
obj = models.表名(键=值,...) obj.save()
改
方式1:
models.表名.objects.filter(pk=1).update(键=值,...)
方式2:
obj = models.表名.objects.filter(pk=1).first() obj.键 = 值 ... obj.save()
删
models.表名.objects.filter(pk=1).delete()
查
必知必会十三个操作:
- all() 查询所有
res = models.表名.objects.all()
- filter() 条件查询
res = models.表名.objects.filter(x=123)
- get() 查询出对象本身,查不到还会报错,也是条件查询,必须携带参数
res = models.表名.objects.get(pk=1)
- first() 取第一个
res = models.表名.object.all().first()
- last() 取最后一个
res = models.表名.object.all().last()
- exclude() 取除此之外的,返回满足条件之外的
res = models.表名.objects.exclude(pk=1)
- values() 返回列表套字典,参数是字段名,不写参数返回所有的键值
res = models.表名.objects.values('字段名')
- values_list() 列表套元组,参数是字段名,不写参数返回所有的值,没有键
res = models.表名.objects.values_List('字段名')
- count() 统计数据的个数,没有参数
res = models.表名.objects.count()
- distinct() 去重,查询出来所有的字段全都一样才可以去重
res = models.表名.objects.values('字段名').distinct()
- order_by() 排序(默认是升序,加负号就是降序)
res = models.表名.objects.order_by('字段名') res = models.表名.objects.order_by('-字段名') res = models.表名.objects.order_by('字段名').reverse()
- reverse() 反转(但是必须是排序好的才可以反转)
res = models.表名.objects.order_by('字段名').reverse()
- exists() 判断查询的东西是否存在
# 简称p用没得 res = models.表名.objects.filter(pk=123).exists()
神奇的双下滑线查询
# 查询价格大于200的书籍 res = models.Book.objects.filter(price__gt=200)
# 查询价格小于200的书籍 res = models.Book.objects.filter(price__lt=200)
# 查询价格大于等于200的书籍 res = models.Book.objects.filter(price__gte=200) # 查询价格小于等于200的书籍 res = models.Book.objects.filter(price__lte=200)
# 查询价格是200或者是300或者是400其中的一个 res = models.Book.objects.filter(price__in=[200, 300, 400]) // 后面只要是可迭代对象就可以了,也可以写成元组
# 查询价格在200到700之间的书籍 res = models.Book.objects.filter(price__range=(200,700)) // 顾头不顾尾
模糊匹配
就是sql语句中的 like
# 查询书籍名称中包含p的书籍 res = models.Book.objects.filter(name__contains='p') // 区分大小写 res = models.Book.objects.filter(name__icontains='p') // 加个i就不区分大小写了
# 查询书籍名称中以'西'开头的书籍 res = models.Book.objects.filter(name__startswitch='西') # 查询数据名称是以'记'结尾的书籍 res = models.Book.objects.filter(name__endswitch='记')
# 查询书籍发布日期为2019年的书籍 res = models.Book.objects.filter(data__year='2019') # 查询书籍发布日期为10月的书籍 res = models.Book.objects.filter(data__month='10')
多表操作
一对多字段增删改查
增
models.表名.objects.create(键=值,外键_id=1) # 外键_id=1 也可以写成 外键=obj
查
res = models.表名.objects.filter(pk=1).first print(res.外键字段) -> 这个拿到的是对应的对象 print(res.外键字段_id) -> 这个拿到的是外键字段对应表的id
改
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)
删
默认是级联删除,所以不要轻易删除数据 models.表名.objects.filter(pk=1).delete() #### 分析 其实一对多的增删改查也就可以把对应的id换成所查询出来的对象,对象默认取得也是id, 也只是键的不同,`键_id`对应`数字`,`键`对应`Queryset对象` ### 多对多字段的增删改查 #### 增 ```python # 为主键为3的书籍添加两个作者1,2 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.add(1,2) 如果两方是多对多关系,有外键的一方可以通过`对象.外键`的方式去设置 add()括号里面也可以传递对象
修改关系
# 修改主键为3的书籍作者为2,3 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.set([2,3]) set()括号里面必须是可迭代对象,里面也是既可以串数字也可以传对象
删除
# 只删除主键为3的书籍的作者2 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.remove(2) -> 指定删除 # 删除主键为3的所有对应关系 book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.clear()
多表查询
ORM跨表查询
- 子查询 - 跨表查询
正反向的概念
- 外键字段在哪里,那个表查被外键关联的表,就是正向 - 谁手里有外键字段 谁就是正向查 - 没有外键字段就是反向 - 正向查询按字段,反向查询按表名小写
题目是最好的理解方式
查询书籍是西游记的出版社名称
1. 方式1(基于对象的跨表查询): book_obj = models.Book.objects.filter(name='西游记').first() res = book_obj.publish.name # publish是外键 2. 方式2(连表查询:正向) res = models.Book.objects.filter(name='西游记').values('publish__name') 3. 方式3(连表查询:反向) res = models.Pubulish.filter(book_name='西游记').values(name)
查询出版社是上海出版社出版的书籍名称
1. 方式1(基于对象的跨表查询): obj = models.Publish.object.filter(name='上海出版社').first() print(obj.book_set) -> app01.Publish.None 这个并不是没查出来,而是因为他是多个值 res = obj.book_set.all() 2. 方式2(连表查询:正向) res = models.Book.objects.filter(publish__name='上海出版社').values('name') 3. 方式3(连表查询:反向) res = models.Publish.object.filter(name='上海出版社').values('book__name')
查询书籍id是4的作者的手机号
1. 方式1(基于对象的跨表查询): book_obj = models.Book.objects.filter(pk=4).first() res = book_obj.authors.all() for i in res: author_obj = models.Author.objects.filter(pk=i.id).first() print(author_obj.AuthorInfo.tel) 2. 方式2(连表查询:正向) res = models.Book.objects.filter(pk=4).values('authors__AuthorInfo__tel') 3. 方式3(连表查询:反向) res = models.AuthorInfo.objects.filter(author__book__id=4).values('tel')