测试环境
Django默认需要整个项目跑起来才可以运行功能函数,如果想测试某个文件需要准备测试环境。(主要指模型层 models.py)
1.python自带测试环境
python Console 但整个是命令行形式 看起来不够直观
2.自己搭建
在自己的app里面创建一个test.py文件
并复制已下代码
from django.test import TestCase
# Create your tests here.
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djmodel.settings')
import django
django.setup()
#需要执行的内容
main()
查看orm底层执行的sql语句
在sttings文件中配置
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
}
}
这样每次运行models命令都会显示对于的sql语句
常用关键字
create
表中新增数据,并有返回值是创建的对象本身
res = models.User.objects.create(name='moon',age=18)
print(res)
# 在数据库表名 user 的表中 插入了一条数据,对应字段数据(name='moon',age=18)
# res就是这条数据本身
filter()
筛选 支持多个条件 默认是 多个条件是and关系
res = models.User.objects.filter(name='moon')
print(res)
# 查询 user表中 字段name 是 moon 的数据对象
# 返回的是 <QuerySet [<User: User object (1)>]> 是一个列表
搭配 first() last() 使用
res = models.User.objects.filter(name='moon').first()
# 拿到查询列表中 第一个数据对象 res=对象
res = models.User.objects.filter(name='moon').last()
# 拿到查询列表中 最后一个数据对象 res=对象
update()
更新数据 搭配筛选来决定更新的个数
# 批量更新
models.User.objects.filter().update()
#没有筛选条件 默认选中的是全部 所以是针对全部更新
# 单个更新
res = models.User.objects.filter(id=1).update(age=22)
print(res)
# 帅选出id=1的数据对象,针对这个对象 进行更新数据 age=22
delete()
删除数据 搭配筛选来决定删除的个数
# 批量删除
models.User.objects.filter().delete()
#没有筛选条件 默认选中的是全部 所以是针对全部删除
# 单个删除
res = models.User.objects.filter(id=1).delete()
print(res)
# 帅选出id=1的数据对象,针对这个对象 进行删除
all()
查询所有数据
models.User.objects.all()
<QuerySet [<User: 用户对象的对象是:duo>, <User: 用户对象的对象是:bo>...]>
# 或得到所有数据对象的类别
values()
指定字段获取内容
models.User.objects.all().values('name')
#获取user表中字段name的所有的值
models.User.objects.filter(id=1).values('name')
# #获取user表中id为1的数据 的 name字段的值
models.User.objects.values('name')
print(res) # <QuerySet [{},{},{}]> 列表套字典
# <QuerySet [{},{},{}]> 列表套字典
values_list()
指定字段获取内容
models.User.objects.values_list('name')
# <QuerySet [('duo',), ('bo',), ('duoduo',), ('bo',), ('hong',)]>
结果是QuerySet[(),(),(),()]列表套元组
distinct()
将查询的结果去重,不影响数据库中的数据
去重条件必须是查询出来的结果必须一模一样 所以不要带主键查询 因为主键都是不同的
models.User.objects.values('name','age').distinct()
# 针对表 user 字段 name 和 age 完全一样的数据去重展示
order_by()
根据指定条件排序 默认升序
models.User.objects.order_by('age')
# user表进行排序 排序根据为age 默认升序 从小到大
models.User.objects.order_by('-age')
# 加上 - 号 就是默认降序 从大到小
count()
统计结果集中数据数据的个数 返回值是整数
models.User.objects.filter(age=22).count()
# 统计user表中 age是22的有几个
# 3
exists()
判断数据中是否有该数据 返回布尔值
models.User.objects.filter(id=1).exists()
# 查看user表中是否有id为1的数据存在
---
True
ORM执行编写SQL语句
复杂数据查询时候orm的操作效率可能比较低 没有原生的sql效率高,我们也可以自己编写sql
关键词 raw
res = models.User.objects.raw('select * from app01_user;')
# 直接编写sql语句去执行
方式二:
from django.db import connection
cursor = connection.cursor()
cursor.execute('select name from app01_user;')
print(cursor.fetchall())
# 利用模块生成 cursor对象 然后利用cursor执行sql语句
# cursor.fetchall() 接收反馈结果
双下划线查询
大于 小于 大于等于 小于等于 区间 包含等查询方式
我们通过models.User.objects.filter()方法可以获得多个符号条件的对象列表
通过.filter()方法获得数据,支持双下划线查询
'''
只要还是queryset对象就可以无限制的点queryset对象的方法
queryset.filter().values().filter().values_list().filter()...
'''
models.User.objects.filter(age__gt=18)
# 查询年龄大于18的数据对象
models.User.objects.filter(age__lt=18)
# 查询年龄小于18的数据对象
models.User.objects.filter(age__gte=18)
#大于等于
models.User.objects.filter(age__lte=18)
#小于等于
models.User.objects.filter(age__in=(18,28,38))
# 查询年龄是 18 或者 28 或者 38的数据对象
models.User.objects.filter(age__range=(10,20))
# 查询年龄从10到20岁 之间 的数据对象
models.User.objects.filter(name__contains='m')
# 查询name字段中 包含 'm' 的数据对象 不包括大写M
models.User.objects.filter(name__icontains='m')
# 也包含大写的M
models.User.objects.filter(register_time__year=2022)
# 查询时间字段里面 年是 2022的数据对象
ORM表外键字段的创建
外键创建的位置
一对多
外键字段建在多的一方
多对多
外键字段统一建在第三张关系表
一对一
建在任何一方都可以 但是建议建在查询频率较高的表中
关系的判断可以采用换位思考原则 熟练的之后可以瞬间判断
一对多 ORM与MySQL一致 外键字段建在多的一方
多对多 ORM比MySQL有更多变化
1.外键字段可以直接建在某张表中(查询频率较高的)
内部会自动帮你创建第三张关系表
2.自己创建第三张关系表并创建外键字段
详情后续讲解
一对一 ORM与MySQL一致 外键字段建在查询较高的一方
代码实操:
一对多
一本书只可以对应一个出版社 一个出版社可以对应很多本书
publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
# 在 书 的表中建立外键 关联 出版社表 在django中会自动关联主键
# on_delete=models.CASCADE 级联删除的意思
多对多
书可以有多个作者 作者也可以有多本书
外键字段名 = models.ManyToManyField(to='关联表名')
# 在 书 表中 建立外键 关联 作者表 ,
# 多对多会自动生成一张表 记录 书对于作者的关系 和 作者对于书的关系
# 针对多对多 不会在表中有展示 而是创建第三张表
一对一
一个作者只可以对应一个信息 一个信息也只可以对应一个作者
author_info = models.OneToOneField(to='Author_info')
# 在作者表中 建立外键 关联 作者信息表
# 一对一外键字段建在查询较高的一方
#针对一对多和一对一同步到表中之后会自动加_id的后缀
外键字段增删改查
一对多 与 一对一的增删改查
在表中插入数据
一对多 与 一对一的增删改查
models.Book.objects.create
(name='西记',price='100',publish_id=1)
# 直接在外键添加实际字段 填写id
增:
publish_obj = models.Publish.objects.filter(pk=2).first()
# 先获取一个出版社对象
models.Book.objects.create
(name='西记',price='100',publish=publish_obj)
# 然后也可以直接把这个对象放入这个外接字段中publish=publish_obj
既可以写实际字段 publish_id='1' 也可以传对象 publish=publish_obj
删:
models.Publish.objects.filter(pk=2).delete()
# 级联删除
改:
models.Publish.objects.filter(pk=2).update(publish_id=2)
models.Publish.objects.filter(pk=2).update(publish=publish_obj)
多对多的增删改查
多对多的增删改查 其实就是针对于第三张表的增删改查
如果给书籍表添加作者
1.先拿到数据对象
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors
# 对象.外键其实已经进入了关系表了
book_obj.authors.add(1)
# 给这个数据对象 绑定一个 id为1的作者
add也可以同时添加多条
book_obj.authors.add(1,3)
# 这样相当于 给书的这个对象 绑定了 1和3 2个id的作者
book_obj.authors.add(author_obj,author_obj2)
# 也支持直接放入一个对象 书的id和这个对象的id会绑定
add是给第三张关系表添加数据 既可以传id 也可以直接传对象
删除:
remove
book_obj.authors.remove(1,3)
# 这样就直接删除了 这个书对于的作者关系
book_obj.authors.remove(author_obj,author_obj2)
# 跟增加一样 也支持直接删除对象
修改:
set
book_obj.authors.set([1,3])
# 把数据对应的作者关系 更改为 这本书 对应作者id为 1和3
# set(括号内必须是可迭代对象 列表 或者 元组)
book_obj.authors.set([author_obj,author_obj2])
# 也支持直接放对象
清空:
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()
# 直接去authors这个表里面取消所有相关的绑定关系
正反向的概念
关键是看 外键字段在哪里
加入由书查出版社
因为外键字段在书内 所以就是正向查询
出版社查书 因为出版社内没有外键字段 就是 反向查询
多表查询
正向查询按字段
反向查询按表名小写
子查询(基于对象的跨表查询)
正向查询
代码演示:
查询书籍id为1的 出版社名称
1、首先要查询到id为1的书籍对象
book_obj = models.Book.objects.filter(pk=1).first()
2. 通过书的对象 查询出版社 属于正向查询 直接按字段查询
book_obj.publish.name
3. 直接通过书籍内关联出版社的外键字段 直接查询
查询书籍主键为1的作者
1、首先要查询到id为1的书籍作者
book_obj = models.Book.objects.filter(pk=1).first()
2. 通过书的对象查询作者属于正向查询 直接可以使用关于作者的外接字段
book_obj.authors.all()
3. 这样就直接拿到了作者对象
查询作者为'moon'的电话号码
1.首先查询到名为 moon 的作者对象
authors_obj = models.Authors.objects.filter(name='moon').first()
authors_obj.info.phone
正反向查询的概念(重要)
正向查询
由外键字段所在的表数据查询关联的表数据 正向
反向查询
没有外键字段的表数据查询关联的表数据 反向
ps:正反向的核心就看外键字段在不在当前数据所在的表中
ORM跨表查询的口诀(重要)
正向查询按外键字段
反向查询按表名小写
反向查询
查询是东方出版社出版的书
拿到东方出版社对象
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
publish_obj.book_set.all()
# 反向查询用表名小写 加_set
查询作者是'moon'写过的书
authors_obj = models.Authors.objects.filter(name='moon').first()
authors_obj.book_set.all()
# 都是先拿到已知的条件获得一个对象 然后判断是反向还是正向
# 正向就直接点外键字段查询 反向就小写表名加_set
'''
当你的查询结果是多个的时候 必须要用 _set.all()
当你的结果直接一个的时候不需要加_set.all()
'''
联表查询(基于双下划线方法的)
正向查询
1.查询作者'moon'的 手机号
authors_obj = models.Authors.objects.filter(name='moon').
values('author_detail__phone')
# 直接在values里面 填写外键字段名 然后直接 __取值
# 反向 models.info.objects.filter(authors__name='moon').valuse(phome)
2.查询数据id为1的出版社名称和书的名称
models.Book.objects.filter(pk=1).values(publish__name,name)
# 反向 models.Publish.objects.filter(book__pk=1).values(name,book__name)
3.查询书籍主键为1的作者姓名
models.Book.objects.filter(pk=1).values(authors__name)
# 反向 models.Authors.objects.filter(book__pk=1).values(name)
标签:obj,name,models,模型,查询,filter,objects,Django
From: https://www.cnblogs.com/moongodnnn/p/16985929.html