Django models.py 模型层(单表多表查询)

模型层

如何查询orm语句内部真正的sql语句的两种方式

  1. 如果是queryset对象,可以直接点query查看
  2. 配置文件中,直接配置
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()

必知必会十三个操作:

  1. all() 查询所有
res = models.表名.objects.all()
  1. filter() 条件查询
res = models.表名.objects.filter(x=123)
  1. get() 查询出对象本身,查不到还会报错,也是条件查询,必须携带参数
res = models.表名.objects.get(pk=1) 
  1. first() 取第一个
res = models.表名.object.all().first()
  1. last() 取最后一个
res = models.表名.object.all().last()
  1. exclude() 取除此之外的,返回满足条件之外的
res = models.表名.objects.exclude(pk=1)
  1. values() 返回列表套字典,参数是字段名,不写参数返回所有的键值
res = models.表名.objects.values('字段名')
  1. values_list() 列表套元组,参数是字段名,不写参数返回所有的值,没有键
res = models.表名.objects.values_List('字段名')
  1. count() 统计数据的个数,没有参数
res = models.表名.objects.count()
  1. distinct() 去重,查询出来所有的字段全都一样才可以去重
res = models.表名.objects.values('字段名').distinct()
  1. order_by() 排序(默认是升序,加负号就是降序)
res = models.表名.objects.order_by('字段名')
res = models.表名.objects.order_by('-字段名')
res = models.表名.objects.order_by('字段名').reverse()
  1. reverse() 反转(但是必须是排序好的才可以反转)
res = models.表名.objects.order_by('字段名').reverse()
  1. 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对象

多对多字段的增删改查

# 为主键为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')
    
原文地址:https://www.cnblogs.com/xiongchao0823/p/11735302.html