Python的Django框架实现数据库查询(不返回QuerySet的方法)


Posted in Python onMay 19, 2020

一、创建模型类:

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
class Course(models.Model):
 """课程表"""
 name = models.CharField(verbose_name='课程名称', max_length=255)
 description = models.TextField(verbose_name='课程描述信息', null=True)
 price = models.DecimalField(verbose_name=u'课程价格', max_digits=15, decimal_places=2, default=0.0)
 deleted = models.BooleanField(verbose_name='课程是否被删除', default=False)
	created_at = models.DateTimeField(auto_now_add=True, db_index=True)
 edited_at = models.DateTimeField(auto_now=True)

 def __repr__(self):
 return self.name

class User(models.Model):
 """用户表:记录用户常用信息"""
 name = models.CharField(verbose_name=u'用户的姓名', max_length=32, null=True)
 mobile = models.CharField(verbose_name=u'用户的手机号', max_length=32, unique=True)
 courses = models.ManyToManyField(verbose_name=u'关联课程', to='Course', through='UserCourse', related_name='user_course')

class UserExtra(models.Model):
 """用户信息额外表: 存储一些用户不常用信息"""
 birthday = models.CharField(verbose_name=u'生日', max_length=32, null=True)
 email = models.EmailField(verbose_name=u'邮箱', null=True)
 user = models.OneToOneField(to=User, related_name='extra') # 跟User表是一对一的关系

class UserCourse(models.Model):
 """课程表跟用户表手动添加的多对多表"""
 course = models.ForeignKey('Course', related_name='my_course')
 user = models.ForeignKey('User', related_name='my_user')

class Coursechapter(models.Model):
 """课程章节表"""
 name = models.CharField(verbose_name='课程名称', max_length=255)
 description = models.TextField(verbose_name='课程描述信息', null=True)
 course = models.ForeignKey('Course', related_name='course_chapter')

执行以下命令,进行数据库的迁移:

python manage.py makemigrations app_name[应用的名称]
python manage.py migrate app_name[应用的名称]

迁移成功后可以进行以下的操作咯~

二、介绍不返回QuerySet的方法:

方法名 介绍
get() 获取单个对象
create() 创建对象
bulk_create() 批量创建对象
get_or_create() 查询对象,若没有找到则创建新的对象
update() 批量更新对象
update_or_create() 更新对象,若没有找到则创建新的对象
delete() 批量删除对象
first() 获取第一个对象
last() 获取最后一个对象
latest() 获取最近的对象
earliest() 获取最早的对象
count() 统计对象的个数
exists() 判断queryset中是否有对象
aggregate() 聚合操作
in_bulk() 根据主键值的列表,批量返回对象
iterator() 获取包含对象的迭代器

三、以上方法的使用:

1.get()方法:

返回按照查询参数匹配到的单个对象,若匹配到的对象个数不只一个的话,会触发MultipleObjectsReturned异常,若根据参数匹配不到对象的时候,会触发DoesNotExist异常。

成功栗子:

try:
 user_obj = models.User.objects.get(mobile=13069636688)
 print(user_obj)
except models.User.DoesNotExist:
 print 'User Not Exist'
# 输出结果:
User object

使用get()方法最好将异常捕获添加上。

获取参数失败栗子:

# 使用get()方法获取一条不存在的数据
user_obj = models.User.objects.get(mobile=13888888888)
# 抛出异常:
DoesNotExist: User matching query does not exist.

# 使用get()方法获取多条数据
user_obj = models.User.objects.get(name='小明')
# 抛出异常:
MultipleObjectsReturned: get() returned more than one User -- it returned 2!

使用ObjectDoesNotExist异常栗子:

DoesNotExist异常从django.core.exceptions.ObjectDoesNotExist继承,可以定位多个DoesNotExist异常,举个栗子:

from django.core.exceptions import ObjectDoesNotExist
try:
 user_obj = models.User.objects.get(mobile=13888888888)
except ObjectDoesNotExist:
 print 'User Not Exist'
# 抛出自定义异常:
User Not Exist

通常我们使用get()方法中的参数,都是查询表中作为唯一标识的字段。

2.create()方法:

create(**kwargs)

在一步操作中同时创建并且保存对象的便捷方法。

举个栗子:

user_obj = models.User.objects.create(mobile=13045621111, name='小牛')
print(user_obj)
# 输出结果如果:
User object

同等于:

user_obj = models.User(mobile=13045621112, name='小牛')
user_obj.save()

3.bulk_create()方法:

bulk_create(objs, batch_size=None)

这种插入比较高效(通常仅一个查询,无论有多少对象),将提供的对象列表插入到数据库中。

举个栗子:

course_obj = models.Course.objects.bulk_create(
 [
 models.Course(name='哈尔滨工业大学'),
 models.Course(name='长春大学')
 ]
)
print course_obj
# 输出结果如下:
[<Course: 哈尔滨工业大学>, <Course: 长春大学>]

注意:

1.不会调用模型的save()方法,所以不会发送pre_save和post_save信号。

2.不适用多张表继承中的子模型。

3.不适用于多对多关系。

4. get_or_create() 方法:

get_or_create(defaults=None, **kwargs)

通过kwargs来查询对象的简便方法(若模型中所有字段都有默认值或可以为空),如果该对象不存在则创建一个新的对象。

该方法返回一个由(object,created)组成的元组,元组中的object是一个查询到或被创建的对象,created是一个表示是否创建新对象的布尔值(true:表示创建新对象|false:相反)。

举个栗子:

try:
 # 通过id=100查看课程是否存在
 course_obj = models.Course.objects.get(pk=100)
except ObjectDoesNotExist:
 # 如果不存在就创建一门课程
 course_obj = models.Course.objects.create(name='上海财经大学', price='1877')

使用get_or_create()方法重写的栗子:

# 查看课程的name="上海交通大学", 如果不存在, 那么创建一条name="信息科技大学",price=2000的数据
obj, created = models.Course.objects\
 .get_or_create(name='上海交通大学',
  defaults={'name': '信息科技大学', 'price': 2000})

print(obj, created)
# 输出结果如下:
Course object True

注意:

​ 1.任何传递给get_or_create()的关键字参数,除了一个可选的defaults,都将传递给get()方法调用。

​ 2.如果找到一个对象,返回一个包含匹配到的对象以及False组成元组。

​ 3.如果查到的对象超过一个以上,将抛出MultipleObjectsReturned异常。

​ 4.如果找不到对象,get_or_create()将会实例化并保存一个新的对象,返回一个由新的对象以及True组成元组。

建议:只在Django视图的POST请求中使用get_or_create(),因为这是一个具有修改性质的动作,不应该使用在GET请求中,那样不安全。

5. update()方法:

update(**kwargs)

对指定的字段执行批量更新操作,并返回匹配的行数

举个栗子:

# 可以更新多个字段,没有多少字段的限制
course_row = models.Course.objects.filter(name='北京大学')\
 .update(name='上海交通大学', price=2000)

print(course_row)
# 输出结果如下:
1 # 表示仅在数据库中修改了一条数据

注意:

​ 1.update()方法无需save()操作,唯一限制是它只能更新模型主表中的列,而不是关联的整个模型。

​ 2.update()方法返回受影响的行数。

​ 3.update()方法还可以防止在加载对象和调用save()之间的短时间内数据库中某些内容可能发生更改的竞争条件。

仅是更新一下对象,不需要为对象做其他事情,最有效的方法是调用update(),而不是将模型对象加载到内存中去。

# 不要这么做的栗子:
course_obj = models.Course.objects.get(name='北京大学')
course_obj.name = '北京大学'
course_obj.save()

6.update_or_create()方法:

update_or_create(defaults=None, **kwargs)

通过给出的kwargs来更新对象的便捷方法, 如果没找到对象,则创建一个新的对象。

defaults是一个由 (field, value)对组成的字典,用于更新对象。defaults中的值可以是可调用对象。

该方法返回一个由(object, created)组成的元组,元组中的object是一个创建的或者是被更新的对象, created是一个标示是否创建了新的对象的布尔值(true(表示创建成功)|false(相反)) 。

举个栗子:

try:
 # 查看课程name="北京大学"存在,若存在那么将name修改成"财经大学"进行保存
 course_obj = models.Course.objects.get(name='北京大学')
 course_obj.name = '财经大学'
 course_obj.save()
except ObjectDoesNotExist:
 # 如果不存在, 则创建一条name="北京大学"的课程
 course_obj = models.Course.objects.create(name='北京大学')

使用update_or_create()方法重写:

# 查找课程name="财经大学"是否存在, 如果存在,将name跟price字段进行更新, 若不存在创建新的记录
obj, res = models.Course.objects\
 .update_or_create(name='财经大学',
  defaults={'name': '复旦大学', 'price': 2080})

print(obj, res)
# 输出结果:
Course object False # 表示没有创建新的对象, 若找到该对象将更新

Course object True # 表示创建了新的对象

7.delete()方法:

delete()

批量删除QuerySet中的所有对象,并返回删除的对象个数和每个对象类型的删除次数的字典。
delete()动作是立即执行的。

举个栗子:

# 删除课程price=2080的所有课程
cur_course =models.Course.objects.filter(price=2080).delete()
print(cur_course)

# 输出结果:
(7, {u'apps.Coursechapter': 2, u'apps.Course': 2, u'apps.UserCourse': 3})
# 分析以上结果, 7表示共删除7条数据, Coursechapter表中2条数据, Course表中2条数据, UserCourse表中3条数据

注意:delete()会为所有已删除的对象(包括级联删除、对象的外键、多对多的关系)发出pre_delete和post_delete信号。

8.first()方法:

first()

返回结果集的第一个对象, 当没有找到时返回None。如果QuerySet没有设置排序,则将会自动按主键进行排序。

举个栗子:

# 获取课程表所有数据中的第一条数据
course_obj = models.Course.objects.all().first()
print(course_obj)
# 输出结果如下:
Course object # 说明获取到了第一条数据

# 获取课程name='农业大学'的第一条数据
course_obj = models.Course.objects.filter(name='农业大学').first()
print(course_obj)
# 输出结果:
None # 说明课程表中没有name='农业大学'

使用[0]来获取第一个对象:

course_obj = models.Course.objects.filter(name='农业大学')[0]
print(course_obj)
# 输出结果:
IndexError: list index out of range # 抛出异常,没有找到并不会返回None

# 如果使用[0]方法,需要添加异常处理
try:
 course_obj = models.Course.objects.filter(name='农业大学')[0]
except IndexError:
 course_obj = None

9.last()方法:

last()

跟first()方法相同,只是返回的是查询集中最后一个对象。

举个栗子:

# 获取课程表中最后一条数据
course_obj = models.Course.objects.last()
print(course_obj)
# 输出结果:
Course object

10.latest()方法:

latest(field_name=None)

使用日期字典field_name,按日期返回最新对象。

举个栗子:

# 查看按创建课程日前返回的最新对象
course_obj = models.Course.objects.filter(created_at__isnull=False).latest('created_at')
print(course_obj.id)
# 输出结果:
101 # 这次是打印的Course表的ID,因为创建课程时, 这就是创建的最新对象。

注意:earliest()和latest()可能会返回空日期的实例,可能需要过滤掉空值 。

11.earliest()方法:

earliest(field_name=None)

跟latest()方法相同,只是返回查询集中按日期最早的对象。

举个栗子:

# 获取课程表中按日期创建课程最早的对象
course_obj = models.Course.objects.filter(created_at__isnull=False).earliest('created_at')
print(course_obj.id)
# 输出结果:
1 # 打印Course表中的ID,因为数据库第一条数据,就是最早创建的

12.count()方法:

count()

返回在数据库中对应的QuerySet对象的个数。

举个栗子:

course_count = models.Course.objects.all().count()
print(course_count)
# 输出结果:

count()永远不会引发异常。

13.exists()方法:

exists()

如果QuerySet包含任何结果,则返回True,否则返回False。

举个栗子:

# 查找课程表中是否包含name="信息科技大学的集合"
course_list = models.Course.objects.filter(name='信息科技大学')
# 如果存在就打印"存在"
if course_list.exists():
 print('存在')
# 输出结果:
存在

该exists()方法快于以下栗子:

# 同样查找课程中是否包含name="信息科技大学"
course_list = models.Course.objects.filter(name='信息科技大学')
if course_list:
 print('存在')
# 输出结果:
存在

14.aggregate()方法:

aggregate(args, *kwargs)

返回汇总值的字典(平均值、总和等),通过QuerySet进行计算,每个参数指定返回的字典中将要包含的值。

举个栗子:

匿名参数的名称将基于聚合函数的名称和模型字段生成

from django.db.models import Count

# 获取课程名称name="信息科技大学",将"name"字段进行聚合统计
course_dict = models.Course.objects.filter(name="信息科技大学").aggregate(Count('name'))
print(course_dict)
# 输出结果:
{u'name__count': 3} # 将基于聚合函数的名称(count)和模型字段(name)生成

再举个栗子:

使用关键字参数来指定聚合函数,可以控制返回的聚合的值的名称。

from django.db.models import Count

# 获取课程名称name="信息科技大学", 将name字段进行聚合统计
course_dict = models.Course.objects.filter(name="信息科技大学")\
 .aggregate(customize_name=Count('name'))
print(course_dict)
# 输出结果:
{'customize_name': 3} # 使用关键字参数指定聚合函数,返回聚合的值名称

15.in_bulk()方法:

in_bulk(id_list=None)

获取主键值的列表,并返回将每个主键值映射到具有给定ID的对象的实例的字典。如果未提供列表,则会返回查询集中所有对象。

举个栗子:

# 获取课程表中ID是1的对象
course_obj = models.Course.objects.in_bulk([1])
print(course_obj)
# 输出结果:
{1: <Course: Course object>}

# 获取课程表中ID是2,3的对象
course_obj = models.Course.objects.in_bulk([2, 3])
print(course_obj)
# 输出结果:
{2: <Course: Course object>, 3: <Course: Course object>}

# 若列表中没有填写ID, 返回空字典
course_obj = models.Course.objects.in_bulk([])
print(course_obj)
# 输出结果:
{}

# 获取课程表所有的ID对应的对象, 返回一个字典
course_obj = models.Course.objects.in_bulk()
print(course_obj)
# 输出结果:
{1: <Course: Course object>, 2: <Course: Course object>, 3: <Course: Course object>, 4: <Course: Course object>, 5: <Course: Course object>, 6: <Course: Course object>,

16.iterator()方法:

iterator()

提交数据库操作,获取QuerySet,返回一个迭代器。

QuerySet通常会再内部缓存其结果,以便再重复计算时不会导致额外的查询。

主要时QuerySet的缓存机制,如果一次从数据库取出很多数据,就有可能导致程序崩溃,可以利用iterator()方法,做性能优化。

举个栗子:

# 取出数据库的所有对象, 要考虑cache机制, 如果数据量太大, 程序就会崩溃
course_list = models.Course.objects.all()

# 利用iterator()方法, 这次就不能用2次for循环, 第一次for循环, 就已经遍历完了
course_set = models.Course.objects.all().iterator()
print(next(course_set))
print(next(course_set))
print(next(course_set))

# 对数据库进行更新, 但并没有执行, 只有再用的时候再执行
models.Course.objects.filter(pk=1).update(price=66)


# 如果for循环2次, 打印2次结果, 也是执行一次sql语句,因为存在sql缓存机制,
# 把第一次查询的结果放到缓存里, 下次从缓存里调
for obj in course_list:
 print(obj.name, obj.price)

"""
# 更新数据之前
id:1
name: 上海交通大学
price: 2000
# 更新数据后
id:1 
name: 上海交通大学
price : 66
"""

使用iterator()会导致先前的prefetch_related()调用被忽略,因为这两个一起优化没有意义。

以上这篇Python的Django框架实现数据库查询(不返回QuerySet的方法)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python中pass语句用法实例分析
Apr 30 Python
在Python中使用sort()方法进行排序的简单教程
May 21 Python
浅谈python import引入不同路径下的模块
Jul 11 Python
python利用rsa库做公钥解密的方法教程
Dec 10 Python
基于并发服务器几种实现方法(总结)
Dec 29 Python
Python数据处理numpy.median的实例讲解
Apr 02 Python
Python实现去除列表中重复元素的方法小结【4种方法】
Apr 27 Python
一看就懂得Python的math模块
Oct 21 Python
python opencv鼠标事件实现画框圈定目标获取坐标信息
Apr 18 Python
Python Lambda函数使用总结详解
Dec 11 Python
python3.4中清屏的处理方法
Jul 06 Python
Python私有属性私有方法应用实例解析
Sep 15 Python
django 数据库返回queryset实现封装为字典
May 19 #Python
使用PyQt的QLabel组件实现选定目标框功能的方法示例
May 19 #Python
python 数据分析实现长宽格式的转换
May 18 #Python
如何把外网python虚拟环境迁移到内网
May 18 #Python
python 实现 hive中类似 lateral view explode的功能示例
May 18 #Python
pandas dataframe 中的explode函数用法详解
May 18 #Python
Python pandas 列转行操作详解(类似hive中explode方法)
May 18 #Python
You might like
如何使用PHP中的字符串函数
2006/11/24 PHP
ThinkPHP3.1新特性之对页面压缩输出的支持
2014/06/19 PHP
PHP函数extension_loaded()用法实例
2015/01/19 PHP
php微信支付之公众号支付功能
2018/05/30 PHP
thinkphp5引入公共部分header、footer的方法详解
2018/09/14 PHP
Javascript的一种模块模式
2008/03/22 Javascript
JavaScript 类的定义和引用 JavaScript高级培训 自定义对象
2010/04/27 Javascript
javascript中数组的冒泡排序使用示例
2013/12/18 Javascript
浅析JS中document对象的一些重要属性
2014/03/06 Javascript
js获取会话框prompt的返回值的方法
2015/01/10 Javascript
详解js中构造流程图的核心技术JsPlumb
2015/12/08 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
2016/09/26 Javascript
解析JavaScript模仿块级作用域
2016/12/29 Javascript
JS实现的tab切换并显示相应内容模块功能示例
2019/08/03 Javascript
jQuery+ajax实现用户登录验证
2020/09/13 jQuery
[06:53]2018DOTA2国际邀请赛寻真——勇于创新的Vici Gaming
2018/08/14 DOTA
python中的字典操作及字典函数
2018/01/03 Python
Python PIL读取的图像发生自动旋转的实现方法
2019/07/05 Python
Python中的几种矩阵乘法(小结)
2019/07/10 Python
python中time库的实例使用方法
2019/10/31 Python
使用python和pygame制作挡板弹球游戏
2019/12/03 Python
Python如何批量获取文件夹的大小并保存
2020/03/31 Python
python pyg2plot的原理知识点总结
2021/02/28 Python
CSS3利用text-shadow属性实现多种效果的文字样式展现方法
2016/08/25 HTML / CSS
使用PDF.JS插件在HTML中预览PDF文件的方法
2018/08/29 HTML / CSS
Yankee Candle官网:美国最畅销蜡烛品牌之一
2020/01/05 全球购物
动物科学专业毕业生的自我评价
2013/11/29 职场文书
客户经理岗位职责
2013/12/08 职场文书
个人简历自我评价
2014/01/06 职场文书
自荐信的基本格式
2014/02/22 职场文书
《永远的白衣战士》教学反思
2014/04/25 职场文书
优秀电子工程系毕业生求职信
2014/05/24 职场文书
道路运输企业安全生产责任书
2014/07/28 职场文书
争先创优个人总结
2015/03/04 职场文书
植物园观后感
2015/06/11 职场文书
写好求职信的技巧解密
2019/05/14 职场文书