配置测试脚本文件

  • 直接在app下面的 test.py 中进行如下配置
  • 注意: 必须完成如下配置之后才能导入我们需要测试的文件
from django.test import TestCase
# 1.从manage.py copy 这几行代码
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day55.settings")
# 2.自己写两行
import django
django.setup() # 3.把上面的环境搭好才能导入我们需要测试的模块
  • 查看内部具体的SQL语句可以将下面的代码copy到settings.py文件的最下方
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
},
},
'loggers': {
'django.db.backends': {
'handlers': ['console'],
'propagate': True,
'level': 'DEBUG',
},
}
}

单表操作

增加数据

增加数据的两种方法

  • 通过QuerySet对象的create方法创建
  • 通过对象的save方法创建
# 1.QuerySet对象的create方法
book_obj = models.Books.objects.create(title='三国演义', price=66.66, publish_date='2019-1-1') # 2.对象的save方法
book_obj = models.Books(title='西游记', price=77.77, publish_date='2018-1-1')
book_obj.save()

查询数据

同样的, 查询数据也有两种方法

  • 通过QuerySet对象的filter方法查询---> 返回的是一个QuerySet对象

  • 通过QuerySet对象的get方法查询---> 返回的就是数据对象

  • 注意: 1. 使用get方法当条件不存在时会报错

    2.orm语句的查询都是惰性查询, 当你使用数据的时候才会执行

    3.只要是QuerySet对象就可以无限制的使用QuerySet的方

           ​          4.只要是QuerySet对象就可以使用 `.query` 的方法 查看当前结果对应的sql语句
# 1.filter
res = models.Books.objects.filter(pk=1).first()
# 查看当前结果对应的sql语句
print(res.query)
'''
SELECT `app01_books`.`id`, `app01_books`.`title`, `app01_books`.`price`, `app01_books`.`publish_date` FROM `app01_books` WHERE `app01_books`.`id` = 1
''' # 2.get
# 查询条件不存在会报错
res = models.Books.objects.get(pk=4)
print(res)
'''
app01.models.DoesNotExist: Books matching query does not exist.
'''

修改数据

  • QuerySet的update的方法
  • 对象.属性进行修改, 然后save方法保存
    • 不推荐使用, 效率低
# 1.QuerySet的update方法
models.Books.objects.filter(pk=1).update(price=88.88) # 2.对象的save()方法
book_obj = models.Books.objects.filter(pk=1).first()
book_obj.price = 66.66
book_obj.save()

删除数据

  • QuerySet的delete方法
  • 对象的delete方法
# 删除数据的两种方法
# 1.query set方法
models.Books.objects.filter(pk=1).delete() # 2.对象方法
book_obj = models.Books.objects.filter(pk=2)
book_obj.delete()

查询十三太保

+----+----------+-------+--------------+
| id | title | price | publish_date |
+----+----------+-------+--------------+
| 1 | 三国演义 | 66.66 | 2019-01-01 |
| 2 | 西游记 | 77.77 | 2018-01-01 |
| 3 | 水浒传 | 88.88 | 2017-01-01 |
| 4 | 红楼梦 | 99.99 | 2016-01-01 |
| 5 | 三国演义 | 66.66 | 2016-01-01 |
+----+----------+-------+--------------+

# 1.all 查询所有, 返回QuerySet对象
res = models.Books.objects.all() # 2.filter 筛选, 返回QuerySet对象
res = models.Books.objects.filter(pk=1, price=66.66) # 3.get 获取的数据对象本身, 条件不存在会报错, 并且条件必须是唯一的, 不然也报错
res = models.Books.objects.get(title='三国演义') # 4.first() 获取QuerySet中的第一个数据对象
res = models.Books.objects.filter().first() # 5.last() 获取QuerySet中最后一个数据对象
res = models.Books.objects.all().last() # 6.count() 统计数据对象的个数
num = models.Books.objects.count()
print(num) # 4 # 7.values() 获取指定的字段数据, 返回的是一个queryset对象, 列表套字典
res = models.Books.objects.values('title', 'price')
print(res) '''
<QuerySet [{'title': '三国演义', 'price': Decimal('66.66')}, {'title': '西游记', 'price': Decimal('77.77')}, {'title': '水浒传', 'price': Decimal('88.88')}, {'title': '红楼梦', 'price': Decimal('99.99')}]>
''' # 8.values_list() 获取指定的字段数据, 返回的是一个queryset对象, 列表套元祖
res = models.Books.objects.values_list('title', 'price')
print(res) '''
<QuerySet [('三国演义', Decimal('66.66')), ('西游记', Decimal('77.77')), ('水浒传', Decimal('88.88')), ('红楼梦', Decimal('99.99'))]>
''' # 9.order_by() 按照字段排序, 返回的是一个QuerySet对象
res1 = models.Books.objects.order_by('price') # 默认是升序
res2 = models.Books.objects.order_by('-price') # 降序
# res = models.Books.objects.all().order_by('price') # 10.reverse() 颠倒顺序, 和order_by联用, 返回的是一个QuerySet对象
res = models.Books.objects.all().order_by('price').reverse() # 11.exclude() 排除, 返回的是一个QuerySet对象
res = models.Books.objects.all().exclude(title='三国演义') # 12.exist() 判断查询结果是否有值, 返回一个布尔值
res = models.Books.objects.filter(pk=1).exists()
print(res) # 13.distinct() 去重, 前提是数据必须是完全相同的情况下, 容易忽略主键
# 主键不同, 因此即使其他字段的值完全一样, 还是会把两个都查询出来
res1 = models.Books.objects.filter(title='三国演义').distinct()
res2 = models.Books.objects.values('title').distinct()
print(res1) # <QuerySet [<Books: Books object>, <Books: Books object>]>
print(res2) # <QuerySet [{'title': '三国演义'}, {'title': '西游记'}, {'title': '水浒传'}, {'title': '红楼梦'}]>

双下划线查询

+----+----------------+-------+--------------+
| id | title | price | publish_date |
+----+----------------+-------+--------------+
| 1 | 三国演义 | 66.66 | 2019-01-01 |
| 2 | 西游记 | 77.77 | 2018-01-01 |
| 3 | 水浒传 | 88.88 | 2017-01-01 |
| 4 | 红楼梦 | 99.99 | 2016-01-01 |
| 5 | 三国演义 | 66.66 | 2016-01-01 |
| 6 | Three kingdoms | 55.55 | 2015-01-01 |
| 7 | Three Kingdoms | 44.44 | 2014-01-01 | Kingdoms 的 King 是大写
+----+----------------+-------+--------------+
# 1.__gt 大于
res = models.Books.objects.filter(price__gt=80)
print(res) # 2.__lt 小于
res = models.Books.objects.filter(price__lt=80)
print(res) # 3.__gte 大于等于
res = models.Books.objects.filter(price__gte=88.88)
print(res) # 4.__lte 小于等于
res = models.Books.objects.filter(price__lte=77.77)
print(res) # 5.__in 或者
res = models.Books.objects.filter(price__in=[88.88, 99.99])
print(res) # 查询结果为空, 是因为我们的价格都是小数, python小数精度很低 # 6.__range 范围(顾头顾尾) 相当于 <= x <=
res = models.Books.objects.filter(price__range=(70, 90))
print(res) # 7.__year
res = models.Books.objects.filter(publish_date__year='2019')
print(res) # 8.__month 月份
res = models.Books.objects.filter(publish_date__month='1')
print(res) """
MySQL 中的模糊查询
关键字: like
符号:
% 匹配任意个数字符
_ 匹配一个字符
""" # 9.__startswith 以...开头
res = models.Books.objects.filter(title__startswith='三国')
print(res) # 10.__endswith 以...结尾
res = models.Books.objects.filter(title__endswith='梦')
print(res) # 11.__contains 包含... (区分大小写)
res = models.Books.objects.filter(title__contains='king')
print(res) # <QuerySet [<Books: Books object>]> # 12.__icontains 包含...(不区分大小写)
res = models.Books.objects.filter(title__icontains='king')
print(res) # <QuerySet [<Books: Books object>, <Books: Books object>]>

连表下的数据增删改

  • 比如我们现在新建的book表, 表中的存在publish_id外键字段, 我们在表中创建数据时, 该如何给这个字段传值呢?

一对多/一对一

# 一对多
# 增加数据
# 1.实际字段, 传外键的id值
models.Book.objects.create(title='三国演义', price='66.66', publish_date='2019-1-1', publish_id=1) # 2.虚拟字段, 直接传对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='西游记', price='77.77', publish_date='2018-1-1', publish=publish_obj) # 修改数据
# 1.实际字段, 传外键id值
models.Book.objects.filter(pk=1).update(publish_id=2) # 2.虚拟字段, 直接传对象
models.Book.objects.filter(pk=2).update(publish=publish_obj) # 删除数据 (默认是级联更新)
models.Publish.objects.filter(pk=1).delete() # 会删除关联表内相应的行

多对多

  • 多对多关系表的数据操作
# add增加多对多关系表数据的两种方法

"""
add方法用于向多对多关系表中添加数据
支持 对象(包含虚拟外键字段)(1, 2) --> 1, 2 代表的还是关联表的id值
也支持 对象(包含虚拟外键字段)(author_obj1, author_obj2)
authors是建立多对多外键时的虚拟字段, book_obj.authors可以理解为进入了多对多关系表中
""" # 先筛选出一个书籍对象
book_obj = models.Book.objects.filter(pk=2).first() # 1.添加id值
book_obj.authors.add(2)
book_obj.authors.add(3, 4) # add方法也支持多个参数 # 2.添加对象
author_obj1 = models.Book.objects.first(pk=2).first()
author_obj2 = models.Book.objects.first(pk=3).first() book_obj.authors.add(author_obj1, author_obj2) # set方法修改多对多关系表中的数据 """
set方法用于修改多对多关系表中的数据
既可传id值, 也可以传对象, 注意!!!必须是可迭代对象!!!
支持多个 """ book_obj = models.Book.objects.filter(pk=4).first()
# 1.添加一个可迭代对象, 里面包含id值
book_obj.authors.set((3, 4))
# 2.添加一个可迭代对象, 里面包含对象
book_obj.authors.set((author_obj1, author_obj2)) # remove方法删除多对多关系表数据 """
remove即可以传id值, 也可以传对象,
并且支持多个, 不需要是可迭代对象
""" book_obj = models.Book.objects.filter(pk=2).first()
# 1.添加id值
book_obj.authors.remove(3, 4)
# 2.添加对象
book_obj.authors.remove(author_obj1, author_obj2) # clear方法可以清空多对多关系表中某个对象的全部数据 """
clear 清空对象的所有数据
"""
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear()

跨表查询

  • 关系字段在A表上, 由A表查B表是 正向查询, 由B表查A表是 反向查询

基本对象的跨表查询 (子查询)

  • 正向查询用: 对象.虚拟字段--->得到对象 (多个结果要 .all() )
  • 反向查询用类名小写: 对象.类名(小写)--->得到对象 (多个结果需要 _set.all() )
# 1.查询书籍主键为2的出版社名称
book_obj = models.Book.objects.filter(pk=2).first()
print(book_obj.publish) # 虚拟字段, 拿到的出版社对象
print(book_obj.publish.name) # 2.查询书籍主键的为3的作者姓名
book_obj = models.Book.objects.filter(pk=4).first()
print(book_obj.authors.all()) # 多个作者对象 """
当我们反向查询的结果可能有多个时, 需要加_set.all()
""" # 3.查询出版社的是东方出版社出版的书
publish_obj = models.Publish.objects.filter(name='东方出版社').first()
print(publish_obj.book_set.all()) # 5.查询作者是alpha写过的书籍
author_obj = models.Author.objects.filter(name='alpha').first()
print(author_obj.book_set.all()) # 6.查询手机号是111的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone='111').first()
print(author_detail_obj.author.name)

基于双下划线的跨表查询 (连表查询)

# 1.查询书籍pk为2的出版社名称
# 正向
res = models.Book.objects.filter(pk=2).values('publish__name')
print(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) # 3.查询作者是bravo的家庭地址
# 正向
res = models.Author.objects.filter(name='bravo').values('author_detail__addr')
print(res)
# 反向
res = models.AuthorDetail.objects.filter(author__name='bravo').values('addr')
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)

Django 05的更多相关文章

  1. Django 05 自定义过滤器、自定义标签

    Django 05 自定义过滤器.自定义标签 一.自定义过滤器 #1.在项目目录下创建一个python package包 取名为common(这个名字可以自定义) #2.在common目录下创建一个t ...

  2. day62 Pyhton 框架Django 05

    内容回顾 1.变量 render(request,'模板文件名',{ k1:v1 }) {{ k1 }} {{ list.0 }} {{ dict.key }} {{ dict.keys }} {{ ...

  3. Django:(05)类视图,装饰器和中间件

    一.类视图的定义和使用 在Django中还可以通过类来定义一个视图,称为类视图. 定义一个类视图:定义一个类,需继承 Django 提供的 View 类 . from django.views.gen ...

  4. Django框架05 /orm单表操作

    Django框架05 /orm单表操作 目录 Django框架05 /orm单表操作 1. orm使用流程 2. orm字段 3. orm参数 4. orm单表简单增/删/改 5. orm单表查询 5 ...

  5. Django REST Framework API Guide 05

    本节大纲 1.Serializer fields 2.Serializer relations Serializer fields 1.serializer 字段定义在fields.py文件内 2.导 ...

  6. Django 2.0 学习(05):Django Admin

    Django Admin 站点的管理者,而非访问者. 创建admin用户 首先,执行下面命令: python manage.py createsuperuser 其次,输入用户名和密码: Userna ...

  7. 05 - Django应用第二步

    知识点 1) 数据库的配置 涉及到INSTALL_APPS的配置等 初次创建数据的命令 2) 模型的编写 模型的创建方式, 写一个类继承自models.Model 模型的数据类型 外键 自动创建ID列 ...

  8. 05 Django与Ajax

      一.Ajax简介 AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”.即使用Javascript语言与服务器进行异步交互, ...

  9. 05.Django基础五之django模型层(一)单表操作

    一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人 ...

随机推荐

  1. C语音中最简单的排序冒泡排序和选择排序代码实现(非指针)

    #include<stdio.h> int main() { int a[5] = { 2,5,7,3,-1 }; int n = sizeof(a) / sizeof(a[0]);//元 ...

  2. 【前端知识体系-JS相关】JS基础知识总结

    1 变量类型和计算 1.1 值类型和引用类型的区别? 值类型:每个变量都会存储各自的值.不会相互影响 引用类型:不同变量的指针执行了同一个对象(数组,对象,函数) 1.2 typeof可以及检测的数据 ...

  3. mongodb存储二进制数据

    mongodb 3.x存储二进制数据并不是以base64的方式,虽然在mongo客户端的查询结果以base64方式显示,请放心使用.下面来分析存储文件的存储内容.base64编码数据会增长1/3成为顾 ...

  4. 你必须知道的容器日志 (2) 开源日志管理方案 ELK

    本篇已加入<.NET Core on K8S学习实践系列文章索引>,可以点击查看更多容器化技术相关系列文章.上一篇<你必须知道的容器日志(1)>中介绍了Docker自带的log ...

  5. 三维目标检测论文阅读:Deep Continuous Fusion for Multi-Sensor 3D Object Detection

    题目:Deep Continuous Fusion for Multi-Sensor 3D Object Detection 来自:Uber: Ming Liang Note: 没有代码,主要看思想吧 ...

  6. 2019-9-25:渗透测试,基础学习,medusa爆破学习

    Medusa(美杜莎)暴力破解使用 该文章仅供学习,利用方法来自网络文章,仅供参考 一.简介 medusa(美杜莎)是一个速度快,支持大规模并行,模块化,爆破登陆,可以同时对多个主机,用户或是密码执行 ...

  7. linux 正确的关机流程

    查看系统的使用状态 1.使用who命令查看在线用户. 2.使用netstat -a或ss -tnl查看网络状态: 3.使用ps -aux 查看后台运行的程序. 通过上述操作可以了解系统目前使用状态,从 ...

  8. 在Asp.Net Core MVC 开发过程中遇到的问题

    1. Q: Razor视图中怎么添加全局模型验证消息 #### A:使用ModelOnly <div asp-validation-summary="ModelOnly" c ...

  9. 相对和绝对路径、cd命令、创建和删除目录、rm命令 使用介绍

    第2周第1次课(3月26日) 课程内容:2.6 相对和绝对路径2.7 cd命令2.8 创建和删除目录mkdir/rmdir2.9 rm命令 2.6相对和绝对路径 任何一个文件都有一个从根开始的路径,绝 ...

  10. PHP经典面试题目汇总

    1.双引号和单引号的区别 双引号解释变量,单引号不解释变量 双引号里插入单引号,其中单引号里如果有变量的话,变量解释 双引号的变量名后面必须要有一个非数字.字母.下划线的特殊字符,或者用{}讲变量括起 ...