Django基础入门⑩:Django查询数据库操作详讲

这篇具有很好参考价值的文章主要介绍了Django基础入门⑩:Django查询数据库操作详讲。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🏘️🏘️个人简介:以山河作礼。
🎖️🎖️:Python领域新星创作者,CSDN实力新星认证,阿里云社区专家博主,CSDN内容合伙人
🎁🎁:Web全栈开发专栏:《Web全栈开发》免费专栏,欢迎阅读!
🎁🎁:文章末尾扫描二维码可以加入粉丝交流群,不定期免费送书。


Django查询数据库操作

基础操作

添加数据

存储数据需要通过save方法进行存储

# 添加数据1
Book(title='张三',price=222,author=Author.objects.get(id=1)).save()
# 添加数据2
# Book.objects.create(title='张三',price=222,author=Author.objects.get(id=1)).save()
# 打印数据
data = Book.objects.all() # 获取全部数据
for book in data:
    print(book.title, book.price, book.author.name)

修改数据

# 修改数据
from datetime import date
book = Book.objects.get(title='张三')
# # book.publish_date = date(2022, 1, 1)
book.price = 555
book.save()  # 更新数据,保存到数据库中

删除数据

# 删除数据
book = Book.objects.get(title='张三')
book.delete()  # 删除数据

查询数据

查询所有书籍:

books = Book.objects.all()

查询 title 字段为 Python 的书籍(精确匹配):

books = Book.objects.filter(title='Python')

其中 filter() 方法对模型进行过滤。这个方法接受关键字参数作为查询条件,可以进行链式操作。

假设我们有一个名为 Person 的模型,其中有一个属性 age 表示人的年龄,我们可以使用如下代码来查询年龄大于等于 18 岁的人:

results = Person.objects.filter(age__gte=18)

在这个例子中,我们使用 filter() 方法对模型进行过滤,传递给它一个查询条件 age__gte=18,其中 gte表示大于等于查询操作符,18 是年龄筛选条件。这个查询可以返回所有年龄大于等于 18 岁的人。

  • 需要注意的是,如果要对查询结果进行多次条件操作,可以使用链式操作。

例如,如果我们需要查询所有年龄大于等于 18 岁且性别为男的人,可以使用以下代码:

results = Person.objects.filter(age__gte=18, gender='male')

在这个例子中,我们在第一次查询过滤后使用了第二次的查询条件 gender='male',即查询所有性别为男,年龄大于等于 18 岁的人。

  • 需要注意的是,在 filter 查询操作中,需要使用双下划线(__)进行多条件查询,例如 age__gte表示查询大于等于指定年龄,gender__icontains 表示查询包含指定性别(不区分大小写)的记录等等。

查询 rating 不等于 1 的书籍:

results = Book.objects.exclude(rating = 1)

其中的 exclude() 方法对模型进行过滤并排除某些不需要的数据,即排除指定查询条件的结果。这个方法与 filter() 方法一样,接受关键字参数作为查询条件,可以进行链式操作。

假设我们有一个名为 Person 的模型,其中有一个属性 age 表示人的年龄,我们可以使用如下代码来排除所有年龄小于 18 岁的人:

results = Person.objects.exclude(age__lt=18)

在这个例子中,我们使用 exclude() 方法对模型进行过滤,传递给它一个排除条件 age__lt=18,其中 lt
表示小于查询操作符,18 是年龄筛选条件。这个查询可以排除所有年龄小于 18 岁的人。

需要注意的是,如果要对查询结果进行多次排除条件操作,可以使用链式操作。例如,如果我们需要排除所有年龄小于 18 岁且没有指定性别的人,可以使用以下代码:

results = Person.objects.exclude(age__lt=18).exclude(gender=None)

在这个例子中,我们在第一次排除过滤后使用了第二次的排除条件 exclude(gender=None),即排除所有性别未知的年龄小于 18岁的人。

  • 需要注意的是,在 exclude 查询操作中,需要使用双下划线(__)进行多条件查询,例如 age__lt表示查询小于指定年龄,gender__icontains 表示查询包含指定性别(不区分大小写)的记录等等。

exclude() 和 filter()方法区别

  • exclude() 和 filter() 方法都是在 Django 中对模型进行查询的常用方法,它们的区别在于查询的方向不同。
  • filter() 方法是对模型查询符合条件的记录,即从数据集中选取数据满足查询条件。而exclude()方法则是从模型中排除不符合查询条件的记录,即从数据集中去除数据不满足查询条件。
  • 在应用时,filter() 方法通常用于基础查询场合,比如查询某个模型中的所有记录、查询符合某个条件的记录等。exclude()方法通常用于复杂的查询场合,比如查询一个模型中的记录中满足某些条件而排除满足其他条件的记录等。

例如,当我们要查询年龄大于等于 18 岁的人时,我们可以使用 filter() 方法:

results = Person.objects.filter(age__gte=18)

当我们要查询年龄不是 18 岁的人时,则需要使用 exclude() 方法:

results = Person.objects.exclude(age=18)

在这个例子中,我们使用 filter() 方法查询年龄大于等于 18 岁的人,而使用 exclude() 方法排除年龄为 18 岁的人。

比较运算符

比较运算符用于筛选符合条件的数据

比较运算符 含义 使用方法
= 等于 Person.objects.filter(age=18)
!= 不等于 Person.objects.exclude(age=18)
> 大于 Person.objects.filter(age__gt=18)
>= 大于等于 Person.objects.filter(age__gte=18)
< 小于 Person.objects.filter(age__lt=18)
<= 小于等于 Person.objects.filter(age__lte=18)
in 在给定的范围内 Person.objects.filter(age__in=[18, 19, 20])
range 在给定的范围内 Person.objects.filter(age__range=(18, 20))
contains 包含指定值 Person.objects.filter(name__contains='Jack')
icontains 包含指定值(不区分大小写) Person.objects.filter(name__icontains='Jack')
startswith 以指定值开头 Person.objects.filter(name__startswith='Jack')
istartswith 以指定值开头(不区分大小写) Person.objects.filter(name__istartswith='Jack')
endswith 以指定值结尾 Person.objects.filter(name__endswith='Smith')
iendswith 以指定值结尾(不区分大小写) Person.objects.filter(name__iendswith='Smith')

逻辑符号

在 Django 中进行查询时,通常需要通过逻辑符将查询条件组合在一起。以下是 Django 查询中需要用到的逻辑符,以及它们的含义和使用方式,以 Markdown 表格的形式列出:

逻辑符 含义 使用方法
Q() 逻辑或( OR ) `Person.objects.filter(Q(age__lt=18)
& 逻辑与( AND ) Person.objects.filter(age__lt=18, gender='male')
\~Q() 逻辑非( NOT ) Person.objects.exclude(~Q(age__lt=18))
  • 逻辑或( OR ):可以使用 Q() 对象联合两个或多个查询条件,实现逻辑或的查询,其中 | 是逻辑或运算符。例如,查询年龄小于 18 岁或性别为男的人可以使用:Person.objects.filter(Q(age__lt=18) | Q(gender='male'))
  • 逻辑与( AND ):可以使用 & 运算符组合多个查询条件,实现逻辑与的查询。例如,查询年龄小于 18 岁且性别为男的人可以使用:Person.objects.filter(age__lt=18, gender='male')
  • 逻辑非( NOT ):可以使用 ~Q() 对象表示查询结果的逆,实现逻辑非的查询,其中 ~ 是逻辑非运算符。例如,查询年龄不是小于 18 岁的人可以使用:Person.objects.exclude(~Q(age__lt=18))

需要注意的是,当多个逻辑运算符混合使用时,需要使用小括号对查询条件进行分组,以保证查询的顺序正确,例如:

from django.db.models import Q

Person.objects.filter(Q(age__lt=18) | (Q(gender='male') & Q(city='北京')))

在这个例子中,使用小括号将 gendercity 的查询条件进行分组,确保查询逻辑正确。

查询 publish_date 在某个时间段以内的书籍:

import datetime

start_date = datetime.date(2021, 1, 1)
end_date = datetime.date(2021, 12, 31)

books = Book.objects.filter(publish_date__range=(start_date, end_date))

values(‘my_field’,‘list_datra’) values获取数据查询集的字段 ,返回字段类型
values_list(‘my_field’,'list_datra) 获取数据查询集的字段 ,返回列表类型

去重查询

from myapp.models import MyModel

# 去重查询,返回去重后的所有 MyModel 对象
distinct_objects = MyModel.objects.all().distinct()

# 去重查询,返回去重后的某个字段的值的集合
distinct_values = MyModel.objects.values('my_field').distinct()

分组集合:

annotate() 方法进行分组集合查询。

from django.db.models import Count
from myapp.models import MyModel

# 获取按照 category 分组后的 count 值,返回分组后的 QuerySet 对象
count_by_category = MyModel.objects.values('category').annotate(count=Count('category'))
  • 可以使用的聚合函数还包括 Sum、Avg、Min 和 Max 等等,你可以根据自己的需要使用不同的聚合函数来计算分组聚合后的结果。

需要注意的是, annotate() 方法和 distinct() 方法一样,都是应用于 QuerySet 对象或相关的 Manager 方法中,并且会创建一个新的查询集。我们还可以使用 filter() 方法和 exclude() 方法对分组对象进行过滤和排除。
例如,你可以按照如下方式获取 category 字段中计数大于 10 的对象:

count_gt_10 = MyModel.objects.values('category').annotate(count=Count('category')).filter(count__gt=10)

在这个示例中,我们在 annotate() 方法之后使用 filter() 方法对分组后的对象进行了过滤,只保留了计数大于 10的对象。

排序查询:

order_by() 方法进行排序查询。

from myapp.models import MyModel

# 对 name 字段进行升序排序
ascending_objects = MyModel.objects.all().order_by('name')

对 name 字段进行升序排序,然后对 age 字段进行降序排序:

# 对 name 字段进行升序排序,对 ages 字段进行降序排序
ascending_then_descending_objects = MyModel.objects.all().order_by('name', '-age')

在这个示例中,我们在 order_by() 方法的第一个参数中指定了 name 字段,并在第二个参数中指定了 -age,表示要对age 字段进行降序排序。

  • 需要注意的是, order_by()方法只能应用于可以比较相等的字段,因此不能用于像二进制字段或大文本字段这样的大对象字段上。此外,排序查询也可以与其他查询方法 filter()exclude()annotate() 等组合使用。

分页操作

Paginator 类实现分页查询。Paginator 是一个支持分页操作的类,可以将一系列对象按照固定的数量分隔成多个页面。

使用 Paginator 类的步骤如下:

  1. 首先,从 Django 的 core.paginator 模块导入 Paginator 类:
from django.core.paginator import Paginator
  1. 接下来,获取一个 QuerySet 或者一个列表数据,通常是从数据库中查询到的:
data_list = MyModel.objects.all()
  1. 使用 Paginator 类对查询到的数据进行分页设置。例如,将查询到的数据划分成每页5个:
paginator = Paginator(data_list, 5)
  1. 最后,从需要显示数据的页面中获取页码并使用 Paginator 对象返回对应的 QuerySet,从而实现分页查询:
page_number = request.GET.get('page') # 获取当前请求的页码
data_page = paginator.get_page(page_number) # 获取对应页码的数据

在这个例子中,我们从请求中获取到需要显示的页码 page_number,然后使用 get_page()
方法返回对应页码的数据。get_page() 方法还可以自动处理非数字或者小于 1 的页码,会返回合法的页码且保持在范围内。如果请求的页码超出范围,get_page() 会返回第一页或最后一页的数据。

需要注意的是, Paginator 类可能会导致大量的查询操作,因此我们在使用它时应该考虑如何优化查询。

模糊查询

使用 QuerySet 的 filter() 方法和 icontains 查询操作符来进行模糊查询。icontains 可以用于查找包含指定字符串的记录,不区分大小写。

例如,如果我们有一个名为 Person 的模型,其中有一个字段 name 表示人名,我们可以使用如下代码来模糊查询名字中包含 “john” 的人:

results = Person.objects.filter(name__icontains='john')
  • __icontains 表示不区分大小写的包含查询操作符,'john' 是要查找的字符串内容。
  • 需要注意的是,进行模糊查询操作时,如果数据集过大,可能会影响性能。在实际开发中,应该根据实际情况使用合理的查询条件和数据库索引来优化查询效率。
  • 在 Django 中,可以使用正则表达式进行模糊查询,具体使用方法是使用 regex 查询操作符和 re模块中的正则表达式语法进行匹配。

假设我们有一个名为 Person 的模型,其中有一个字段 name 表示人名,我们可以使用如下代码来使用正则表达式查询名字中包含字母 “j” 或 “o” 的人:

import re

pattern = r'[jo]'
results = Person.objects.filter(name__regex=pattern)

需要注意的是,使用正则表达式进行模糊查询需要注意以下几点:

  1. 正则表达式不是 SQL 的一部分,查询速度可能会比简单的 SQL 查询慢,因此尽量减少正则表达式的使用,只在必要时使用。
  2. 正则表达式的语法较为复杂,需要了解正则表达式的语法和用法才能使用。
  3. 正则表达式匹配的查询条件应该根据实际情况进行优化,尽量减少不必要的模式匹配过程,以提高查询效率。

多表查询

在 Django 中,可以使用相关对象和 filter() 方法进行多表查询。相关对象是指模型类中通过 ForeignKey、OneToOneField 或 ManyToManyField 字段所定义的关联关系。

假设我们有两个模型类 AuthorBook,其中 Book 模型类通过 ForeignKey 字段关联到了 Author 模型类,表示一本书只能属于一位作者。现在我们想要查询所有书名以 “Django” 开头的作者及其所写的所有书籍,代码示例如下:

from myapp.models import Author, Book

authors = Author.objects.filter(book__title__startswith='Django')

在这里我们首先导入 AuthorBook 模型类,然后使用 filter() 方法对 Author 模型类进行过滤,筛选条件为 book__title__startswith='Django',其中 bookAuthor模型中的 ForeignKey 关联字段,titleBook 模型类中的属性名,表示书籍的名称,startswith是字符串查询操作符,表示筛选书名以 “Django” 开头的记录。

通过上述查询,我们可以得到所有书籍名以 “Django” 开头的作者,接着通过 Author 模型类中的 book_set 属性获取每个作者所写的所有书籍,示例代码如下:

for author in authors:
    books = author.book_set.all()
    for book in books:
        print(author.name, book.title)

在这里,我们使用 for 循环遍历每个查询到的作者实例对象,然后使用 author.book_set.all()获取该作者所写的所有书籍。由于 Book 模型类中 ForeignKey 关联字段默认生成的 related_name 属性为book_set,因此我们可以使用 author.book_set 获取该作者所写的所有书籍。接着再使用 for循环遍历每本书,输出书籍名称和作者名称。

  • 需要注意的是,如果是多个模型之间的复杂查询,最好使用 Django 内置的 ORM 或第三方的 QueryBuilder来进行多表查询,而不是直接编写原生 SQL 语句,这样可以提高开发效率并避免 SQL 注入安全问题。

执行原生 SQL

Django 提供了游标 cursor 对数据库进行增删改操作,在 Django 中执行非查询语句必须使用游标进行操作。游标 cursor 定义在 django.db.connection 包中,使用前用下面的方式进行导入:

from django.db import connection

用创建 cursor 类的构造函数创建 cursor 对象,再使用 cursor 对象执行 SQL 语句。为确保能够在出现异常时释放 cursor 游标,通常使用 with 语句进行创建操,如下所示:

from django.db import connection
with connection.cursor() as cur:
    cur.execute('执行SQL语句')

使用示例如下:文章来源地址https://www.toymoban.com/news/detail-539843.html

from django.db import connection

with connection.cursor() as cur:
    #调用游标对象的execute方法,更新author的名字
    cur.execute('update index_author set name="Jack" where id=3;')

with connection.cursor() as cur: 
    # 删除id为3的一条author记录 
    cur.execute('delete from index_author where id=3;')

with connections.cursor() as cursor:
    cursor.execute('SELECT * FROM my_table WHERE some_field > %s', [some_value])
    result = cursor.fetchall()
  • 开发建议使用 Django ORM 中的高级查询,例如 filterexcludeannotatevalues
    等方法,这些方法可以构建复杂的查询条件,并且支持链式调用,便于代码维护和可读性。
  • ORM 查询的好处是它是语言级别的,且与数据库类型无关,使你的代码更加可移植。ORM 还提供了自动构造 SQL查询语句的功能,省去了手动构造 SQL 语句的繁琐和容易出错的过程。
  • 当然,在某些特定情况下,ORM 查询不能满足需求,例如需要执行复杂的聚合函数,或者需要执行跨数据库的 SQL 查询。这时候可以考虑使用Django 的 connections 模块执行原生 SQL 查询,但需要注意避免 SQL 注入攻击。

到了这里,关于Django基础入门⑩:Django查询数据库操作详讲的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Django笔记二十八之数据库查询优化汇总

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十八之数据库查询优化汇总 这一篇笔记将从以下几个方面来介绍 Django 在查询过程中的一些优化操作,有一些是介绍如何获取 Django 查询转化的 sql 语句,有一些是理解 QuerySet 是如何获取数据的。 以下是本篇笔记目录: 性

    2023年04月22日
    浏览(82)
  • Django基本数据库操作

    @ 目录 Django基本数据库操作 👨‍🏫内容一:基本数据库配置 👨‍🔬内容二:ORM基本操作 👉Django是一个流行的Python Web框架,它可以使用不同的数据库引擎来存储和管理数据。Django默认使用sqlite数据库,但是你也可以配置它使用mysql数据库。这里我将配置的是本地的Mysql数据

    2024年02月16日
    浏览(42)
  • Django笔记二十一之使用原生SQL查询数据库

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十一之使用原生SQL查询数据库 Django 提供了两种方式来执行原生 SQL 代码。 一种是使用 raw() 函数,一种是 使用 connection.cursor()。 但是官方还是推荐在使用原生 SQL 之前,尽量的先去探索一下 QuerySet 提供的各种 API。 目前而言

    2023年04月10日
    浏览(61)
  • [django] django好玩的地方在于,可以批量操作数据库了

    django好玩的地方在于,可以批量操作数据库了。 和数据库快速交互,真的是好厉害。 这种情况怎么过滤 objects.filter project = models.ForeignKey(to=“Project”, verbose_name=‘项目’, on_delete=models.CASCADE, max_length=50, null=False, help_text=‘项目’) mysql json类型的字段 models.JSONField 在django中是什

    2024年02月22日
    浏览(40)
  • Django操作MySQL数据库的优化方法

    Django 是一个很流行的 Web 框架,而 MySQL 是常用的关系型数据库之一。在使用 Django 开发 Web 应用时,我们经常需要使用 MySQL 存储数据,因此如何加速 MySQL 是我们需要关注的问题。本文将介绍一些方法来优化 Django 中 MySQL 的性能。 使用适当的索引 索引是 MySQL 中提高查询性能的

    2024年02月10日
    浏览(72)
  • Django的数据库操作的游标(cursor)方法

    在Django中,数据库操作的游标方法是一种直接与数据库进行交互的方式,它提供了更底层的数据库访问能力。通过游标方法,你可以执行原始的SQL查询、事务处理以及处理大量数据等操作。 Django的数据库游标方法主要通过 connection 对象来执行,其中 connection 对象表示与数据库

    2024年02月13日
    浏览(40)
  • Django ORM:数据库操作的Python化艺术

    Django的对象关系映射器(ORM)是其核心功能之一,允许开发者使用Python代码来定义、操作和查询数据库。这篇文章将带你深入了解Django ORM的强大之处,从基本概念到高级查询技巧,提供丰富的示例帮助你掌握使用Django ORM进行有效和高效的数据库操作。 Django ORM的目的是提供一

    2024年02月04日
    浏览(61)
  • Django笔记二十二之多数据库操作

    本文首发于公众号:Hunter后端 原文链接:Django笔记二十二之多数据库操作 这一篇笔记介绍一下多数据库操作。 在第十篇笔记的时候,简单介绍过 using() 的使用方法,多个数据库就是通过 using(db_alias) 的方式来来指定选中的数据库,这里介绍一下同步库表结构时候的操作。 定

    2023年04月11日
    浏览(60)
  • 数据库作业——select查询操作

    创建数据库 插入数据 1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号,不显示重复的部门号。 3、求出所有职工的人数。 4、列出最高工和最低工资。 5、列出职工的平均工资和总工资。 6、创建一个只有职工号、姓名和参加工作的新表,名为工作日期表。

    2024年02月13日
    浏览(52)
  • 数据库实验一:基本表操作、基本数据查询和复杂数据查询

    按下图创建四个表:teacher、student、course和SC,为属性选择合适的域、合适的主码和外键约束,并为他们插入所列出数据; 中文语义 teacher (TID,TNAME,DEPT,SALARY) 教师(教工号,姓名,系,薪水) student (SID,SNAME,DEPT,AGE,GENDER) 学生(学号,姓名,系,年龄,性别) course (CID,CNAME,DE

    2024年02月01日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包