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

一、创建模型类:

# -*- 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的方法)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Django框架获取form表单数据方式总结

    Django中获取text,password 名字:<input type="text" name="name"><br><br> 密码:<input type="password" name="password"> Form表单提交数据时使用的是post方式,所以在后端接收参数的时候需要先判断请求方式为post时才能请求到数据 name = request.POST.get('

  • django admin 根据choice字段选择的不同来显示不同的页面方式

    我就废话不多说了,大家还是直接看代码吧! 一.举例 tip/tip.js var react = function () { if (django.jQuery('#id_tiptype').val() == 'content') { django.jQuery('#id_content').parent().parent().show(500); django.jQuery('#id_image').parent().parent().hide(500); django.jQuery('#id

  • 在Python的Django框架中更新数据库数据的方法

    先使用一些关键参数创建对象实例,如下: >>> p = Publisher(name='Apress', ... address='2855 Telegraph Ave.', ... city='Berkeley', ... state_province='CA', ... country='U.S.A.', ... website='http://www.apress.com/') 这个对象实例并 没有 对数据库做修改. 在调用`` save()`` 方法之前,记录并没有保存至数据库,

  • Python Django form 组件动态从数据库取choices数据实例

    app01/models.py: from django.db import models class UserInfo(models.Model): username = models.CharField(max_length=16) password = models.CharField(max_length=16) mobile = models.CharField(max_length=11) class City(models.Model): name = models.CharFie

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

    一.创建模型类: # -*- 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.Tex

  • 在Python的Django框架中获取单个对象数据的简单方法

    相对列表来说,有些时候我们更需要获取单个的对象, `` get()`` 方法就是在此时使用的: >>> Publisher.objects.get(name="Apress") <Publisher: Apress> 这样,就返回了单个对象,而不是列表(更准确的说,QuerySet). 所以,如果结果是多个对象,会导致抛出异常: >>> Publisher.objects.get(country="U.S.A.") T

  • Python的Django框架中的select_related函数对QuerySet 查询的优化

    1. 实例的背景说明 假定一个个人信息系统,需要记录系统中各个人的故乡.居住地.以及到过的城市.数据库设计如下: Models.py 内容如下: from django.db import models class Province(models.Model): name = models.CharField(max_length=10) def __unicode__(self): return self.name class City(models.Model): name = models

  • Python的Django框架中设置日期和字段可选的方法

    设置字段可选 在摆弄了一会之后,你或许会发现管理工具有个限制:编辑表单需要你填写每一个字段,然而在有些情况下,你想要某些字段是可选的. 举个例子,我们想要Author模块中的email字段成为可选,即允许不填. 在现实世界中,你可能没有为每个作者登记邮箱地址. 为了指定email字段为可选,你只要编辑Book模块(回想第五章,它在mysite/books/models.py文件里),在email字段上加上blank=True.代码如下: class Author(models.Model): f

  • Python的Django框架中forms表单类的使用方法详解

    Form表单的功能 自动生成HTML表单元素 检查表单数据的合法性 如果验证错误,重新显示表单(数据不会重置) 数据类型转换(字符类型的数据转换成相应的Python类型) Form相关的对象包括 Widget:用来渲染成HTML元素的工具,如:forms.Textarea对应HTML中的<textarea>标签 Field:Form对象中的一个字段,如:EmailField表示email字段,如果这个字段不是有效的email格式,就会产生错误. Form:一系列Field对象的集合,负责验证和

  • Python的Django框架中从url中捕捉文本的方法

    每个被捕获的参数将被作为纯Python字符串来发送,而不管正则表达式中的格式. 举个例子,在这行URLConf中: (r'^articles/(?P<year>\d{4})/$', views.year_archive), 尽管 \d{4} 将只匹配整数的字符串,但是参数 year 是作为字符串传至 views.year_archive() 的,而不是整型. 当你在写视图代码时记住这点很重要,许多Python内建的方法对于接受的对象的类型很讲究. 许多内置Python函数是挑剔的(这是理所当然

  • Django框架ORM数据库操作实例详解

    本文实例讲述了Django框架ORM数据库操作.分享给大家供大家参考,具体如下: 测试数据:BookInfo表 PeopleInfo表 一.增加 1.save: 对象 = 模型类( 字段名 = 值, 字段名 = 值, - ) 对象.save() 例: >>> book = BookInfo( ... name='python入门', ... pub_date='2010-1-1' ... ) >>> book.save() >>> book <B

  • Django框架多表查询实例分析

    本文实例讲述了Django框架多表查询.分享给大家供大家参考,具体如下: 多表查询是模型层的重要功能之一, Django提供了一套基于关联字段独特的解决方案. ForeignKey 来自Django官方文档的模型示例: from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() class Author(mod

  • Python使用django框架实现多人在线匿名聊天的小程序

    最近看到好多设计类网站,都提供了多人在线匿名聊天的小功能,感觉很有意思,于是基于python的django框架自己写了一个,支持手动实时更名,最下方提供了完整的源码. 在线聊天地址(无需登录,开一个窗口,代表一个用户): http://zhaozhaoli.vicp.io/chatroom/happy/ 移动端聊天效果图: 网页版聊天效果图: 实现思路: 发送的消息通过ajax先写入数据库,通过ajax的循环请求,将写入数据库的消息显示到前端界面. 前端核心代码: <script> $(fun

  • Python及Django框架生成二维码的方法分析

    本文实例讲述了Python及Django框架生成二维码的方法.分享给大家供大家参考,具体如下: 一.包的安装和简单使用 1.1 用Python来生成二维码很简单,可以看 qrcode 这个包: pip install qrcode qrcode 依赖 Image 这个包: pip install Image 如果这个包安装有困难,可选纯Python的包来实现此功能,见下文. 1.2 安装后就可以使用了,这个程序带了一个 qr 命令: qr 'http://www.ziqiangxuetang.c

随机推荐