[Python] Django ORM与执行原生SQL实现操作数据库(上)

简介: [Python] Django ORM与执行原生SQL实现操作数据库(上)

前言

系列文章目录

[Python]目录

🍉 ORM

在Django MVT设计模式中的Model,专门负责和数据库进行交互,对应的文件 models.py。Model中内嵌了ORM框架,使得我们不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据库表的增删改查。

ORM框架就是把数据库表中的行与相应模型类的对象相对应,把数据库中的表与模型类相对应,把数据库中表的字段与模型类的属性相对应。

使用ORM框架操作数据库,我们可以不用关心底层具体使用的是哪个数据库,只需要关心ORM框架即可。如果需要使用不同的数据库,我们只需要在Django框架中进行相应的配置,ORM会自动连接对应的数据库,如果需要对数据库进行增删改查,我们也只需要操作ORM即可,ORM会自动生成对应的数据库的sql语言。

🍉 shell

Django的manage工具提供了shell命令,以便我们可以直接在终端中执行测试python语句。

Django manage提供的shell类似于ipython;

使用shell工具,可以帮助我们更好的测试代码,对于有关模型的代码(数据对象的增删改查)可以使用shell进行测试,就不用书写路由和请求响应到浏览器客户端进行查看。

启动shell,在命令窗口运行:

python manage.py shell

测试,导入两个模型类,并查询两个模型类对应的所有数据对象:

# 导入两个模型类
from book.models import BookInfo,PeopleInfo
# 查询两个模型类对应的所有数据对象
BookInfo.objects.all()
PeopleInfo.objects.all()

有关模型类的代码写在models.py中,对数据进行增删改查的代码书写在views.py中,对数据进行增删改查需要实例化模型类,在views.py中导入模型类,对数据进行增删改查。

🍉 模型类与数据的准备

🍒 模型类

from django.db import models
# Create your models here.
class BookInfo(models.Model):
    name = models.CharField(max_length=10, unique=True, verbose_name='书籍名')
    pub_date = models.DateField(null=True)  # 发布日期
    read_count = models.IntegerField(default=0)  # 阅读数
    comment_count = models.IntegerField(default=0)  # 评论数
    is_delete = models.BooleanField(default=False)  # 是否被逻辑删除
    class Meta:
        db_table = 'bookinfo'  # 指定模型对应数据库中表的表名
        verbose_name = '书籍信息'  # 修改后台admin显示的表名
    def __str__(self):
        return self.name
# 准备人物列表信息的模型类
class PeopleInfo(models.Model):
  # 性别的可选值 0对应male 1对应female
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    name = models.CharField(max_length=20, verbose_name='名称')  # 人物的名字
    gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')  # 人物的性别
    description = models.CharField(max_length=200, null=True, verbose_name='描述信息')  # 人物的描述信息
    book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 引用外键,引用的模型为BookInfo
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')  # 是否被逻辑删除
    class Meta:
        db_table = 'peopleinfo'
        verbose_name = '人物信息'
    def __str__(self):
        return self.name

🍒 数据

表 bookinfo:

insert into bookinfo(name, pub_date, read_count,comment_count, is_delete) values
('射雕英雄传', '1980-5-1', 12, 34, 0),
('天龙八部', '1986-7-24', 36, 40, 0),
('笑傲江湖', '1995-12-24', 20, 80, 0),
('雪山飞狐', '1987-11-11', 58, 24, 0);

表 peopleinfo:

insert into peopleinfo(name, gender, book_id, description, is_delete)  values
    ('郭靖', 1, 1, '降龙十八掌', 0),
    ('黄蓉', 0, 1, '打狗棍法', 0),
    ('黄药师', 1, 1, '弹指神通', 0),
    ('欧阳锋', 1, 1, '蛤蟆功', 0),
    ('梅超风', 0, 1, '九阴白骨爪', 0),
    ('乔峰', 1, 2, '降龙十八掌', 0),
    ('段誉', 1, 2, '六脉神剑', 0),
    ('虚竹', 1, 2, '天山六阳掌', 0),
    ('王语嫣', 0, 2, '神仙姐姐', 0),
    ('令狐冲', 1, 3, '独孤九剑', 0),
    ('任盈盈', 0, 3, '弹琴', 0),
    ('岳不群', 1, 3, '华山剑法', 0),
    ('东方不败', 0, 3, '葵花宝典', 0),
    ('胡斐', 1, 4, '胡家刀法', 0),
    ('苗若兰', 0, 4, '黄衣', 0),
    ('程灵素', 0, 4, '医术', 0),
    ('袁紫衣', 0, 4, '六合拳', 0);

🍉 查询数据

🍒 查询集

查询集,也称查询结果集(QuerySet),表示从数据库中获取的对象集合,查询集不是简单的列表。

当调用如下方法时,Django会返回查询集:

1.all()

2.filter()

3.exclude()

4.values()

5.distinct()

🍓 查询集的特性

🍎 惰性执行

创建的查询集不会立即访问数据库将数据查询出来,直到调用查询数据的时候,才会访问数据库将数据库中满足条件的数据查询出来。

🍎 缓存

如果多次数据查询使用的是同一个查询集,则只有第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。如果多个查询集无法重用缓存,则每次查询都会与数据库进行一次交互,增加了数据库的负载。经过存储后,可以重用查询集,第一次查询后的查询可以直接使用缓存中的数据,减少了数据库的查询次数。

🍒 简单查询

对数据进行增删改查都可以通过调用模型类的模型管理类对象objects来实现

🍓 all():查询模型对应数据表中所有数据

all()方法可以一次性查询出模型对应的数据表中所有的数据,且该方法返回的结果为QuerySet对象。

all()方法返回的QuerySet对象是一个由数据表中所有数据记录组成的列表。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.通过objects调用all()方法获取BookInfo模型对应数据表中的所有数据

books = BookInfo.objects.all()

🍓 get():查询数据表中满足指定条件的数据

注意,get()方法只能用于查询查询结果唯一的情况,get()方法只能用于查询返回符合要求只有一条数据的情况,当查询结果中没有记录或者记录超过一条时都会报错抛出异常。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.通过objects调用get()方法获取BookInfo模型对应数据表中符合条件的数据记录

book = BookInfo.objects.get(id=8)
>>> from subapp01.models import BookInfo
>>> book = BookInfo.objects.get(id=8)    
>>> book                                 
<BookInfo: 射雕英雄传>
>>> book.name
'射雕英雄传'
>>> book.read_count
12
>>>

🍓 values():获取需要的字段

values()方法可以用于获取需要的字段,该方法返回的为一个QuerySet对象,该对象包含的数据类型为由指定的字段和值形成的字典。

values()方法返回的QuerySet对象是一个由数据记录字段和值组成的字典形成的列表。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用values()方法获取BookInfo模型对应数据表中数据记录的指定字段

# 查询出所有数据记录后筛选出数据记录的id、name、read_count字段
books = BookInfo.objects.all().values('id', 'name', 'read_count')
>>> from subapp01.models import BookInfo  # 导入模型
>>> books = BookInfo.objects.all().values('id', 'name', 'read_count')
>>> books
<QuerySet [{'id': 8, 'name': '射雕英雄传', 'read_count': 12}, {'id': 9, 'name': '天龙八部', 'read_count': 36}, {'id': 10, 'name': '笑傲江湖', 'read_count': 20}, {'id': 11, 'name': '雪山飞狐', 'read_count': 58}]>
>>> books[0] 
{'id': 8, 'name': '射雕英雄传', 'read_count': 12}
>>> books[0]['name']
'射雕英雄传'
>>>

🍓 distinct():对查询出来的数据记录进行去重

该方法用于去除重复数据,返回的为一个QuerySet对象,该对象中包含的数据为去重之后的数据。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用distinct()方法对查询出来的数据记录进行去重

data = BookInfo.objects.all().values('is_delete').distinct()

>>> from subapp01.models import BookInfo  # 导入模型
>>> data = BookInfo.objects.all().values('is_delete').distinct()
>>> data
<QuerySet [{'is_delete': False}]>
>>>

🍓 count():统计查询结果中数据记录的数量

该方法返回查询结果中数据记录的数量。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用count()方法对查询出来的数据记录进行数量的统计

count = BookInfo.objects.all().count()
>>> from subapp01.models import BookInfo
>>> count = BookInfo.objects.all().count()
>>> count
4
>>>

🍒 过滤查询 filter() & get() & exclude()

使用filter()、get()、exclude()进行过滤查询相当于SQL中的where语句select * from 表 where 条件语句

filter():筛选符合条件的n个结果(n的取值为0-n)。返回结果为一个QuerySet对象,该对象是一个由数据记录组成的列表。

get():筛选符合条件的1个结果(返回结果只能一个,大于一个会报错),返回一个数据记录对象

exclude():排除掉符合条件之后剩下的数据组成的结果集,该结果集是一个QuerySet对象,该对象是一个由数据记录组成的列表,相当于条件语句中not。

🍓 语法

以filter()为例

filter(字段名__运算符=值)

字段名和运算符间使用两个下划线进行分割,所以属性名不能包括多个下划线。

🍓 运算符

  • 相等
  • exact:表示判等。
  • 模糊查询
  • contains:是否包含。
  • 说明:如果要包含%无需转义,直接写即可。
  • startswith、endswith:以指定值开头或结尾。
  • 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
  • 空查询
  • isnull:是否为null。
  • 范围查询
  • in:是否包含在范围内。
  • 比较查询
  • gt大于 (greater then)
  • gte大于等于 (greater then equal)
  • lt小于 (less then)
  • lte小于等于 (less then equal)
  • 不等于的运算符,使用exclude()过滤器。
  • 日期查询
  • year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

🍓 相等

exact:表示判等。

# 查询编号为1的图书
# exact相当于 等于号
book = BookInfo.objects.get(id__exact=1)
# 简写形式
book = BookInfo.objects.get(id=1)

# exact相当于 等于号
book = BookInfo.objects.filter(id__exact=1)
# 简写形式
book = BookInfo.objects.filter(id=1)

返回结果为一个QuerySet对象,该对象是一个由数据记录组成的列表。

🍓 模糊查询

  • contains:是否包含。
  • 说明:如果要查询数据中是否包含%,无需转义,直接写%即可。
  • startswith、endswith:以指定值开头或结尾。
  • 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
# 查询书名包含'湖'的图书
# 不知道返回结果有几个,使用filter
# 包含 运算符 contains
# 如果要包含%无需转义,直接写即可
books = BookInfo.objects.filter(name__contains='湖')

# 查询书名以'部'结尾的图书
# 不知道返回结果有几个,使用filter
# startswith、endswith:以指定值开头或结尾。
books = BookInfo.objects.filter(name__endswith='部')

🍓 空查询

isnull:是否为null。

# 查询书名为空的图书
books = BookInfo.objects.filter(name__isnull=True)

🍓 范围查询

in:是否包含在范围内。

# 查询编号为1或3或5的图书
books = BookInfo.objects.filter(id__in=[1, 3, 5])

🍓 比较查询

  • gt大于 (greater then)
  • gte大于等于 (greater then equal)
  • lt小于 (less then)
  • lte小于等于 (less then equal)
  • 不等于的运算符,使用exclude()过滤器。
# 查询编号大于3的图书
books = BookInfo.objects.filter(id__gt=3)

# 查询编号不大于3的图书
books = BookInfo.objects.exclude(id__gt=3)

🍓 日期查询

year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

# 查询1980年发表的图书
books = BookInfo.objects.filter(pub_date__year='1980')

# 查询1990年1月1日后发表的图书
books = BookInfo.objects.filter(pub_date__gt='1990-1-1')

注意:

日期的格式只能YYYY-MM-DD

🍒 F对象(两个属性进行比较)

之前的查询都是对象的属性与常量值比较,如果需要两个属性之间进行比较,则使用F对象,F对象被定义在django.db.models中。

🍓 语法

以filter为例

filter(字段名__运算符=F('字段名'))
from django.db.models import F
# 查询阅读量大于等于评论量的图书。
books = BookInfo.objects.filter(read_count__gt=F('comment_count'))

# 查询阅读量大于2倍评论量的图书。
books = BookInfo.objects.filter(read_count__gt=F('comment_count') * 2)

🍒 Q对象(逻辑或与非查询)

如果需要实现逻辑或or、逻辑与and、逻辑非not的查询,则可以使用Q()对象结合|&~运算符进行数据的查询,Q对象被义在django.db.models中。

🍓 语法

# 以逻辑或查询为例
Q(属性名__运算符=值)|Q(属性名__运算符=值)|Q(属性名__运算符=值)|···

🍓 逻辑与查询

Q对象可以使用&连接,&表示逻辑与。

from django.db.models import Q
# 查询阅读量大于20,并且编号小于3的图书。
# 方法一: 进行多次过滤得到结果
books = BookInfo.objects.filter(read_count__gt=20).filter(id__lt=3)
# 方法二:
books = BookInfo.objects.filter(read_count__gt=20, id__lt=3)
# 方法三:使用Q对象相与
books = BookInfo.objects.filter(Q(read_count__gt=20) & Q(id__lt=3))

🍓 逻辑或查询

逻辑或查询只能使用Q对象实现

Q对象可以使用|连接,|表示逻辑或。

# 查询阅读量大于20,或编号小于3的图书
books = BookInfo.objects.filter(Q(read_count__gt=20) | Q(id__lt=3))

🍓 逻辑非查询

Q对象前可以使用~操作符,表示逻辑非 not。

# 查询编号不等于3的图书。
books = BookInfo.objects.exclude(id=3)
books = BookInfo.objects.filter(~Q(id=3))

相关文章
|
6月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS费用价格:MySQL、SQL Server、PostgreSQL和MariaDB引擎收费标准
阿里云RDS数据库支持MySQL、SQL Server、PostgreSQL、MariaDB,多种引擎优惠上线!MySQL倚天版88元/年,SQL Server 2核4G仅299元/年,PostgreSQL 227元/年起。高可用、可弹性伸缩,安全稳定。详情见官网活动页。
1116 152
|
6月前
|
关系型数据库 MySQL 数据库
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎
阿里云数据库RDS支持MySQL、SQL Server、PostgreSQL和MariaDB引擎,提供高性价比、稳定安全的云数据库服务,适用于多种行业与业务场景。
858 156
|
6月前
|
SQL 人工智能 Linux
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
585 5
SQL Server 2025 RC1 发布 - 从本地到云端的 AI 就绪企业数据库
|
9月前
|
SQL 关系型数据库 MySQL
Go语言数据库编程:使用 `database/sql` 与 MySQL/PostgreSQL
Go语言通过`database/sql`标准库提供统一数据库操作接口,支持MySQL、PostgreSQL等多种数据库。本文介绍了驱动安装、连接数据库、基本增删改查操作、预处理语句、事务处理及错误管理等内容,涵盖实际开发中常用的技巧与注意事项,适合快速掌握Go语言数据库编程基础。
1078 213
|
5月前
|
SQL 存储 监控
SQL日志优化策略:提升数据库日志记录效率
通过以上方法结合起来运行调整方案, 可以显著地提升SQL环境下面向各种搜索引擎服务平台所需要满足标准条件下之数据库登记作业流程综合表现; 同时还能确保系统稳健运行并满越用户体验预期目标.
326 6
|
6月前
|
关系型数据库 分布式数据库 数据库
阿里云数据库收费价格:MySQL、PostgreSQL、SQL Server和MariaDB引擎费用整理
阿里云数据库提供多种类型,包括关系型与NoSQL,主流如PolarDB、RDS MySQL/PostgreSQL、Redis等。价格低至21元/月起,支持按需付费与优惠套餐,适用于各类应用场景。
|
6月前
|
SQL Oracle 关系型数据库
Oracle数据库创建表空间和索引的SQL语法示例
以上SQL语法提供了一种标准方式去组织Oracle数据库内部结构,并且通过合理使用可以显著改善查询速度及整体性能。需要注意,在实际应用过程当中应该根据具体业务需求、系统资源状况以及预期目标去合理规划并调整参数设置以达到最佳效果。
429 8
|
7月前
|
SQL 人工智能 Java
用 LangChain4j+Ollama 打造 Text-to-SQL AI Agent,数据库想问就问
本文介绍了如何利用AI技术简化SQL查询操作,让不懂技术的用户也能轻松从数据库中获取信息。通过本地部署PostgreSQL数据库和Ollama模型,结合Java代码,实现将自然语言问题自动转换为SQL查询,并将结果以易懂的方式呈现。整个流程简单直观,适合初学者动手实践,同时也展示了AI在数据查询中的潜力与局限。
874 8
|
9月前
|
Linux 数据库 数据安全/隐私保护
Python web Django快速入门手册全栈版,共2590字,短小精悍
本教程涵盖Django从安装到数据库模型创建的全流程。第一章介绍Windows、Linux及macOS下虚拟环境搭建与Django安装验证;第二章讲解项目创建、迁移与运行;第三章演示应用APP创建及项目汉化;第四章说明超级用户创建与后台登录;第五章深入数据库模型设计,包括类与表的对应关系及模型创建步骤。内容精炼实用,适合快速入门Django全栈开发。
427 1
|
8月前
|
SQL XML Java
配置Spring框架以连接SQL Server数据库
最后,需要集成Spring配置到应用中,这通常在 `main`方法或者Spring Boot的应用配置类中通过加载XML配置或使用注解来实现。
632 0

推荐镜像

更多