配置测试脚本文件

  • 直接在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. lqb 基础练习 01字串 (itoa)

    基础练习 01字串 时间限制:1.0s   内存限制:256.0MB     问题描述 对于长度为5位的一个01串,每一位都可能是0或1,一共有32种可能.它们的前几个是: 00000 00001 0 ...

  2. pat 1035 Password(20 分)

    1035 Password(20 分) To prepare for PAT, the judge sometimes has to generate random passwords for the ...

  3. hdu 1162 Eddy's picture (prim)

    Eddy's pictureTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  4. drf组件之jwt认证

    drf组件之jwt认证模块 一.认证规则 全称:json web token 解释:加密字符串的原始数据是json,后台产生,通过web传输给前台存储 格式:三段式 - 头.载荷.签名 - 头和载荷才 ...

  5. 【Linux系列】Centos 7安装 Redis(六)

    目的 本文主要介绍以下两点: 一. 安装Redis 二. 设置开机启动项 演示 一. 安装Redis 打开Redis官网,右击复制链接. yum install -y gcc # 先更新下编译环境 c ...

  6. Java Import的使用

    这里根据上一篇中ClassObject.java的例子改编的:https://www.cnblogs.com/jizizh/p/11938574.html 一.创建ClassObjectImport. ...

  7. 分享一个撩妹、装13神技能,0基础用Python暴力破解WiFi密码

    WiFi密码Python暴力破解   Python密码破解部分截图 获取视频资料,转发此文+点击喜欢,然后获取资料请加Python交流群:580478401,就可以获取视频教程+源码 环境准备: py ...

  8. Netty学习篇⑥--ByteBuf源码分析

    什么是ByteBuf? ByteBuf在Netty中充当着非常重要的角色:它是在数据传输中负责装载字节数据的一个容器;其内部结构和数组类似,初始化默认长度为256,默认最大长度为Integer.MAX ...

  9. /etc/security/limits.conf 详解与配置

    目录 一. /etc/security/limits.conf 详解 /etc/security/limits.conf 配置解析 /etc/security/limits.d/ 目录 二. ulim ...

  10. mysql中运用条件判断筛选来获取数据

    ### part1 单表查询 sql查询完整语法: select .. from .. where .. group by .. having .. order by .. limit .. 一.wh ...