Python web实战之 Django 的 ORM 框架详解

news2025/1/19 13:11:25

8d8e8b4196f2412ba8d5e7e961cf7823.png


本文关键词:Python、Django、ORM。

概要

在 Python Web 开发中,ORM(Object-Relational Mapping,对象关系映射)是一个非常重要的概念。ORM 框架可以让我们不用编写 SQL 语句,就能够使用对象的方式来操作数据库,大大提高了代码的可读性和可维护性。Django 作为一款流行的 Web 框架,自带了强大的 ORM 框架。

本文将会详细介绍 Django 的 ORM 框架,包括基本使用方法、高级查询、性能优化等方面。


 

1. 基本使用方法

1.1 定义模型类

在 Django 里可以使用模型类来定义数据库表。模型类需要继承自 django.db.models.Model,并且定义表的各个字段。例如,下面是一个简单的模型类,用来表示一个博客文章:

from django.db import models

class Blog(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)

上面的代码定义了一个 Blog 类来表示博客文章。这个类继承自 django.db.models.Model,并且定义了三个字段:标题、内容和发布日期。其中,标题和内容都是字符串类型,使用 CharField 和 TextField 来定义。pub_date 是一个日期时间类型,使用 DateTimeField 来定义。auto_now_add=True 表示在创建新记录时自动设置为当前时间。

1.2 创建表

定义完模型类之后,我们需要创建对应的数据库表。在 Django 中,可以使用 manage.py 命令来进行数据库迁移操作。具体来说,我们需要执行以下两个命令:

# 生成迁移文件
python manage.py makemigrations

# 执行迁移操作
python manage.py migrate

执行完上面的两个命令之后,Django 会根据模型类自动生成对应的数据库表。

注意:在进行迁移操作之前,请确保已经仔细确认了所有相关设置和代码,并且备份了数据。

1.3 插入数据

插入数据可以使用模型类来表示一条记录,并且调用 save() 方法来将记录保存到数据库中。例如,下面的代码演示了如何向 Blog 表中插入一条记录:

blog = Blog(title='Hello World', content='This is my first blog post.')
blog.save()

1.4 查询数据

查询数据可以使用模型类的 objects 属性,该属性是 Manager 类的实例,提供了各种查询方法。例如从 Blog 表中查询所有记录:

blogs = Blog.objects.all()

for blog in blogs:
    print(blog.title, blog.content, blog.pub_date)

1.5 更新数据

更新数据可以先查询出需要更新的记录,然后修改对应的字段,最后调用 save() 方法进行保存。例如将 Blog 表中所有记录的标题修改为 'Hello Django'

blogs = Blog.objects.all()

for blog in blogs:
    blog.title = 'Hello Django'
    blog.save()

1.6 删除数据

删除数据可以先查询出需要删除的记录,然后调用 delete() 方法进行删除。例如删除 Blog 表中所有记录:

blogs = Blog.objects.all()

for blog in blogs:
    blog.delete()

 

2. 高级查询

2.1 条件查询

Django 的 ORM 框架提供了非常方便的条件查询功能。例如查询 Blog 表中标题为 'Hello World' 的记录:

blogs = Blog.objects.filter(title='Hello World')

for blog in blogs:
    print(blog.title, blog.content,blog.pub_date)

可以看到,我们使用了 filter() 方法来指定查询条件,其中 title='Hello World' 表示标题等于 'Hello World'filter() 方法返回一个 QuerySet 对象,可以使用 for 循环遍历查询结果。

2.2 聚合查询

聚合查询可以使用 aggregate() 方法来实现。例如统计 Blog 表中记录的数量:

from django.db.models import Count

count = Blog.objects.aggregate(Count('id'))
print(count['id__count'])

可以看到,我们使用了 aggregate() 方法来指定聚合操作,其中 Count('id') 表示统计 id 字段的数量。aggregate() 方法返回一个字典,其中键是聚合操作的名称(例如,id__count 表示统计数量),值是聚合操作的结果。

2.3 连接查询

连接查询可以使用 select_related() 方法和 prefetch_related() 方法来实现。例如,下面的代码演示了如何查询 Blog 表中的记录,并且同时连接查询关联的 Author 表中的作者信息:

class Author(models.Model):
    name = models.CharField(max_length=50)

class Blog(models.Model):
    title = models.CharField(max_length=100)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)

blogs = Blog.objects.select_related('author')

for blog in blogs:
    print(blog.title, blog.content, blog.pub_date, blog.author.name)

可以看到,我们使用了 select_related('author') 方法来指定需要连接查询的外键字段(即 author 字段),这样就可以同时查询 Blog 表和 Author 表中的数据。注意,select_related() 方法只能用于一对一和多对一关系的查询,上面的例子是多对一关系。

2.4 原生 SQL 查询

Django 的 ORM 框架也支持原生 SQL 查询。例如使用原生 SQL 查询 Blog 表中的记录:

from django.db import connection

with connection.cursor() as cursor:
    cursor.execute("SELECT * FROM myapp_blog")
    blogs = cursor.fetchall()

for blog in blogs:
    print(blog[1], blog[2], blog[3])

可以看到,我们使用了 connection.cursor() 方法来获取数据库连接的游标,然后调用 execute() 方法执行 SQL 查询。最后,使用 fetchall() 方法获取查询结果。

 

3. 性能优化

3.1 使用索引

索引是提高数据库查询性能的重要手段。在 Django 中,可以使用 db_index=True 参数来为字段创建索引。例如为 title 字段创建索引:

class Blog(models.Model):
    title = models.CharField(max_length=100, db_index=True)
    content = models.TextField()
    pub_date = models.DateTimeField(auto_now_add=True)

3.2 批量操作

批量操作可以使用 bulk_create() 方法和 bulk_update() 方法来实现。例如,下面的代码演示了如何批量插入 Blog 表中的记录:

blogs = [
    Blog(title='Blog 1', content='Content 1'),
    Blog(title='Blog 2', content='Content 2'),
    Blog(title='Blog 3', content='Content 3'),
]

Blog.objects.bulk_create(blogs)

可以看到,我们使用了 bulk_create() 方法来批量插入记录,其中 blogs 是一个包含多个 Blog 实例的列表。

3.3 延迟加载

延迟加载可以使用 defer() 方法和 only() 方法来实现。

使用 defer() 方法时,Django 将不会立即从数据库中获取指定字段的数据。它会在需要访问这些字段的数据时,再去查询数据库。这样可以避免一次性从数据库中取出大量的数据,减轻数据库的负担,提高查询效率。

使用 only() 方法可以指定只查询需要的字段,而不是查询整个表的所有字段。这样可以减少数据传输的大小,节省网络带宽和内存资源,提高查询效率。

例如延迟加载 Blog 表中的记录,并且只查询 title 和 pub_date 两个字段:

blogs = Blog.objects.defer('content').only('title', 'pub_date')

for blog in blogs:
    print(blog.title, blog.pub_date)

可以看到,我们使用了 defer('content') 方法来延迟加载 content 字段,这样查询结果中就不会包含 content 字段的数据。同时,使用 only('title', 'pub_date') 方法来指定只查询 title 和 pub_date 两个字段的数据。

3.4 缓存查询结果

缓存查询结果可以使用 Django 的缓存框架来实现。Django的缓存框架可以配置为使用不同的缓存后端,下面是常见的几种缓存后端的配置方法:

3.4.1 内存缓存

使用内存缓存作为缓存后端是最简单的配置方式,它可以快速地缓存数据并且不需要额外的配置。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
        'LOCATION': 'unique-snowflake',
    }
}

BACKEND 指定了缓存后端为内存缓存,LOCATION 是一个可选的参数,用于指定缓存的名称,可以是任何字符串。

3.4.2 文件缓存

使用文件缓存作为缓存后端可以将缓存数据存储到文件系统中,需要指定缓存文件的路径。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
        'LOCATION': '/var/tmp/django_cache',
    }
}

BACKEND 指定了缓存后端为文件缓存,LOCATION 是一个必选的参数,用于指定缓存文件的路径。

3.4.3 Memcached

使用Memcached作为缓存后端可以将缓存数据存储到Memcached服务器中,需要指定Memcached服务器的地址和端口号。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    }
}

BACKEND 指定了缓存后端为Memcached,LOCATION 是一个必选的参数,用于指定Memcached服务器的地址和端口号。

3.4.4 Redis

使用Redis作为缓存后端可以将缓存数据存储到Redis服务器中,需要指定Redis服务器的地址、端口号和数据库编号。在settings.py文件中进行如下配置:

CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/0',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
        },
    }
}

BACKEND 指定了缓存后端为Redis,LOCATION 是一个必选的参数,用于指定Redis服务器的地址、端口号和数据库编号。OPTIONS 是一个可选的参数,用于指定Redis客户端的选项,这里使用默认选项。

需要注意的是,在使用Redis作为缓存后端时,需要额外安装 django-redis 库。可以使用pip命令进行安装:

pip install django-redis

例如缓存 Blog 表中的记录:

from django.core.cache import cache

blogs = cache.get('blogs')

if blogs is None:
    blogs = Blog.objects.all()
    cache.set('blogs', blogs, timeout=3600)

for blog in blogs:
    print(blog.title, blog.content, blog.pub_date)

可以看到,我们使用了 cache.get('blogs') 方法来从缓存中获取查询结果。如果缓存中不存在查询结果,则使用 Blog.objects.all() 来查询数据库,并且使用 cache.set('blogs', blogs, timeout=3600) 方法将查询结果存入缓存中。其中,timeout=3600 表示缓存的过期时间为 3600 秒。

 

技术总结

本文详细介绍了 Django 的 ORM 框架,包括基本使用方法、高级查询和性能优化等方面。ORM 框架可以让我们不用编写 SQL 语句,就能够使用对象的方式来操作数据库,大大提高了代码的可读性和可维护性。同时,我们还介绍了一些性能优化技巧,例如使用索引、批量操作、延迟加载和缓存查询结果等。希望本文对你学习 Django 的 ORM 框架有所帮助!

 

欢迎点赞收藏转发,感谢🙏

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/829047.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

总结946

6:40起床 7:15~8:00早读,07年tex1,2 8:10~10:12 880第二章选填,题目有些综合,错的有些多呀,不要紧,拿下它,就有进步了。 10:28~11:27重做强化18讲6道题 12:10~2:15吃饭睡觉&…

MySQL 三大日志日志:undo log、redo log、binlog

目录 一条SQL的执行流程 为什么需要 undo log? undo log 是如何刷盘(持久化到磁盘)的? 为什么需要 Buffer Pool? Buffer Pool 缓存什么? Undo 页是记录什么? 查询一条记录,就只需…

代码随想录算法训练营第三十二天 | Leetcode随机抽题检测

Leetcode随机抽题检测 46 全排列未看解答自己编写的青春版重点题解的代码日后复习重新编写 78 子集未看解答自己编写的青春版重点题解的代码日后复习重新编写 17 电话号码的字母组合未看解答自己编写的青春版重点题解的代码日后复习重新编写 39 组合总和未看解答自己编写的青春…

SpringBoot项目增加logback日志文件

一、简介 在开发和调试过程中,日志是一项非常重要的工具。它不仅可以帮助我们快速定位和解决问题,还可以记录和监控系统的运行状态。Spring Boot默认提供了一套简单易用且功能强大的日志框架logback,本文将介绍如何在Spring Boot项目中配置和…

使用AIGC工具提升安全工作效率

新钛云服已累计为您分享760篇技术干货 在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于: 开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、…

HTML基础介绍2

表单格式化 ctrld&#xff1a;复制选中行数的所有代码 ctrlx&#xff1a;删除代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>表单综合案例</title> </head> <body> <!--…

(AcWing)01背包问题

有 N 件物品和一个容量是 V 的背包。每件物品只能使用一次。 第 ii 件物品的体积是 vi&#xff0c;价值是 wi。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。 输入格式 第一行两个整数N&#xff0c;V&…

0基础学习VR全景平台篇 第76篇:全景相机-圆周率全景相机如何直播推流

圆周率科技&#xff0c;成立于2012年&#xff0c;是中国最早投身嵌入式全景算法研发的团队之一&#xff0c;亦是全球市场占有率最大的全景算法供应商。相继推出一体化智能屏、支持一键高清全景直播的智慧全景相机--Pilot Era和Pilot One&#xff0c;为用户带来实时畅享8K的高清…

【AGI】世界首次实现室温超导LK-99

论文&#xff1a;The First Room-Temperature Ambient-Pressure Superconductor GPT论文总结&#xff1a; 根据所提供的信息&#xff0c;这篇论文报道了一种在室温和常压下工作的室温超导体LK-99。LK-99的超导性是通过微小的结构畸变引起的&#xff0c;而不是通过温度和压力等外…

快速部署外卖系统:利用现代工具简化开发流程

在竞争激烈的外卖市场中&#xff0c;快速部署高效稳定的外卖系统是餐饮企业成功的关键之一。本文将介绍如何利用现代工具简化外卖系统的开发流程&#xff0c;并附带代码示例&#xff0c;帮助开发者快速搭建功能完备、用户友好的外卖平台。 1. 简介 在外卖业务快速增长的背景…

c++编写坦克大战(同年回忆)全网最全的讲解

c编写坦克大战 项目前言 需要熟练的掌握c语言&#xff0c;c。熟练掌握各种数据类型和数据结构。拥有优秀的文档阅读能力&#xff08;设计EasyX图形库的使用&#xff09;&#xff0c;拥有一个漂亮温柔的女朋友。 环境准备 我这里使用的是VS2022,还需要安装EasX图形库。安装教程…

C算法——生成牌 洗牌算法

生成牌 // // Created by Lenovo on 2022-06-11-下午 3:15. // 作者&#xff1a;小象 // 版本&#xff1a;1.0 //#include <stdio.h> #include <time.h> #include <stdlib.h>#define M 1 // 基数 #define N 20 // 洗牌次数 #define TOTAL_NUMS (N - M 1) …

uniapp运行项目到iOS基座

2022年9月&#xff0c;因收到苹果公司警告&#xff0c;目前开发者已无法在iOS真机设备使用未签名的标准基座&#xff0c;所以现在要运行到 IOS &#xff0c;也需要进行签名。 Windows系统&#xff0c;HBuilderX 3.6.20以下版本&#xff0c;无法像MacOSX那样对标准基座进行签名…

c++基于游戏壳的飞机大战游戏----开发(第二部分)

c基于游戏壳的飞机大战游戏----开发&#xff08;第二部分&#xff09; 一.我们先将每个功能按文件夹进行分类&#xff08;这样便于管理&#xff09; 如下 每一个文件里都写出相应的头文件与源文件&#xff08;GameFrame文件夹中的内容是上一篇博客中写好的游戏壳代码&#xf…

【汇总】解决Ajax请求后端接口,返回ModelAndView页面不跳转

【汇总】解决Ajax请求后端接口&#xff0c;返回ModelAndView不跳转 问题发现问题解决方法一&#xff1a;直接跳转到指定URL&#xff08;推荐&#xff09;方法二&#xff1a;将返回的html内容&#xff0c;插入到页面某个元素中方法三&#xff1a;操作文档流方法四&#xff1a;使…

【雕爷学编程】MicroPython动手做(28)——物联网之Yeelight 2

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

KubeSphere 3.4.0 发布:支持 K8s v1.26

2023 年 07 月 26 日&#xff0c;KubeSphere 开源社区激动地向大家宣布&#xff0c;KubeSphere 3.4.0 正式发布&#xff01; 让我们先简单回顾下之前三个大版本的主要变化&#xff1a; KubeSphere 3.1.0 新增了“边缘计算”、“计量计费” 等功能&#xff0c;将 Kubernetes 从…

【uniapp】【Vue3】 超简单全局自定义弹窗组件Modal

Element-Plus 自动引入&#xff0c;Icon图标不显示 //这样写是不会显示的 <el-icon size"20"><view /> </el-icon>// 应该这样写 <el-icon size"20"><i-ep-view/> </el-icon>// 或 <i-ep-view/>这个名字怎么去…

SpringBoot+ruoyi框架图片上传和文件下载

第一次接触ruoyi框架&#xff0c;碰到文件上传和下载问题&#xff0c;今天来总结一下。 使用若依框架文件上传下载首先配置文件路径要配好。 文件下载&#xff1a; application.yml若依配置 # 项目相关配置 ruoyi:# 名称name: RuoYi# 版本version: 3.6.0# 版权年份copyright…

《向量数据库指南》——向量数据库Milvus Cloud、Pinecone、Vespa、Weaviate、Vald、GSI 、 Qdrant选哪个?

1、Milvus Cloud(https://milvuscloud.com) Milvus是一个开源的向量数据库,支持高效的向量搜索和相似度匹配。它针对大规模向量数据集的性能进行了优化,并提供了Python、Java、Go和C++等多种语言的客户端接口。Milvus在图像、音频、文本和推荐等领域都有广泛的应用。 2…