目录
简介:
本章节将基于模型层操作数据库里面的表了,不再是之前的单表操作;此次引入了表的设计、基于外键字段增删改查、基于对象跨表查询、基于双下划线跨表查询。
单表查询实验环境准备
我们需要新建一个Django项目,为了便于我们更加方便操作模型层,有两种方式可以直接调用到模型层。
方式一:在Django自带的测试环境
方式二:在项目内的任意py文件内,推荐在应用下面的一个tests.py文件进行
import os
if __name__ == "__main__":
# 注意:mysite.settings修改成自己的!!项目名.settings
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
import django
django.setup() # 以独立的方式运行Django程序
# 以下编辑我们需要的代码:
我们实验就使用Sqlite数据库了,首先要启动一下Django项目,然后这个数据库就被创建起来了,再使用pycharm进行连接:
选择Sqlite数据库路径(默认在项目根路径下)注意:一定要选中当前Django项目路径,如果选中错误,后面就会看不到我们创建的表了。
试验前夕环境准备完毕,接下来该准备数据库表了。
一、单表查询
1.1 创建实验表
在开始前,我们先在models.py文件里面创建如下实验表:
# 每个表的ID字段默认创建,会自动设置成主键且自增
# 每个表的ID字段默认创建,会自动设置成主键且自增
class Test(models.Model): # 表名
author = models.CharField(max_length=30) # 作者名称
title = models.CharField(max_length=30) # 书籍名称
price = models.FloatField() # 书籍价格
publish = models.CharField(max_length=30) # 出版社名称
在项目根目录下再进行数据库迁移命令:
python3 manage.py makemigrations
python3 manage.py migrate
此时刷新一下sqllite就可以看到我们创建的表
我们现在可以对这个表进行操作了!
1.2 实例
tests.py,保持这种格式
import os
if __name__ == "__main__":
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Day06.settings")
import django
django.setup()
# 需要编写的代码放在这行注释下面:
先对表增加几条数据,我们就可以执行这个tests.py文件。
from app01.models import Test
Test.objects.create(author='张三',title='斗破苍穹',price=80.5,publish='武汉出版社')
Test.objects.create(author='李四',title='西游记',price=85.5,publish='北京出版社')
Test.objects.create(author='王五',title='水浒传',price=79.0,publish='北京出版社')
此时我们再来查询看看效果,我们对但条记录有两种方式查询:
- filter括号内可以放多个参数 默认是and关系 推荐使用 条件不符合不会报错
- get括号内可以放多个参数 默认是and关系 不推荐使用 条件不符合直接报错
filter拿到的是一个QuerySet对象
,而get直接拿到的就是结果。但是程序是尽可能避免出错情况的,所以我们这里以filter作为查询方式
# QuerySet对象类似于列表,该列表内包含了filter查询到的结果。
obj = Test.objects.filter(title='斗破苍穹').first()
print(obj.author,obj.publish) # 拿到的是一个对象,该对象包含了这一条记录的所有值。
执行结果:
张三 武汉出版社
演示:当使用fileter与get查询不存在的记录时
print(Test.objects.filter(title='error'))
print(Test.objects.get(title='error'))
效果所示:get也就比filter快一步拿到结果,但是遇到没找到记录时它会报错,而filter不会
使用filter
查询到的结果都会放到一个QuerySet对象
里面去,而里面存储的就是对象的形式查询结果,可以通过QuerySet
里面取出的对象.字段名
拿到数据。
1.3 查看ORM使用的SQL语句
当返回的结果还是QuerySet对象的时候,我们可以通过query
查看一下SQL语句是如何执行的
obj = Test.objects.filter(title='斗破苍穹')
print(obj)
print(obj.query)
打印结果
方式二:实现我们使用ORM执行查询操作时在终端显示SQL语句
通过在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',
},
}
}
那么此时我们再进行ORM查询操作那么就会在终端打印SQL语句
obj = models.Test.objects.filter(title='斗破苍穹')
print(obj)
执行效果如下:
补充:
当我们需要查询某个表的主键值=1
的数据,那么我们就需要知道主键对应的字段名是什么,通常是id;但是为了避免有些表的主键字段名不是id的情况,此时我们可以通过填写字段时加上pk
参数就可以直接对应到主键字段了;
obj = Test.objects.fileter(pk=1); # 获取Test表主键字段值为1的数据
1.3 单表查询常用方法
上面只是粗略介绍了一下,常规如何进行单表查询操作,这里介绍一些常用的查询API,可以更简便的帮助我们日后来操作表。
1、all() 查询所有元素
2、filter() 它包含了与所给筛选条件相匹配的对象
3、get() 返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
4、first() 获取第一个元素
obj = Test.objects.all().first() # QuerySet对象里面第一个元素
print(obj)
print(obj.title)
# Test.objects.all()[0] 这种方式也是可以取到第一个元素的
# 但是如果没有元素可取则会报错,而使用first()则返回None
执行结果:
Test object (1)
斗破苍穹
5、last() 获取最后一个元素
obj = Test.objects.last()
print(obj)
print(obj.title)
执行结果
Test object (3)
水浒传
当我们需要对整个表的记录进行查询时,可以忽略all()。如:Test.objects.first() == Test.objects.all().first()
6、values() 获取指定字段的值
obj = Test.objects.values('title','publish')
print(obj)
执行结果
<QuerySet [{
'title': '斗破苍穹', 'publish': '武汉出版社'}, {
'title': '西游记', 'publish': '北京出版社'}, {
'title': '水浒传', 'publish': '北京出版社'}]>
此时我们也可以通过first()、last()、[]
等取值。
7、value_list() 获取指定字段的值
它与values()
的区别是:value_list()
返回的是列表套元组,也就是说没有对应字段名了,只有字段值
obj = Test.objects.values_list('title','publish')
print(obj)
执行结果
<QuerySet [('斗破苍穹', '武汉出版社'), ('西游记', '北京出版社'), ('水浒传', '北京出版社')]>
8、order_by() 排序
根据某个字段进行排序